home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung CD 2 (Tewi)(1994).iso / c / compiler / micro_c / cintro.doc < prev    next >
Text File  |  1992-02-23  |  117KB  |  2,498 lines

  1.    
  2.    
  3.    
  4.    
  5.    
  6.    
  7.    
  8.    
  9.    
  10.    
  11.    
  12.    
  13.                                       An
  14.                                  Introduction
  15.                                       to
  16.    
  17.    
  18.                                      CCC
  19.                                     CC CC
  20.                                    CC   CC
  21.                                    CC
  22.                                    CC   CC
  23.                                     CC CC
  24.                                      CCC
  25.    
  26.    
  27.                                     Using
  28.                              The MICRO-C Compiler
  29.    
  30.    
  31.    
  32.    
  33.    
  34.    
  35.    
  36.    
  37.    
  38.    
  39.                               Revised: 14-Jan-92
  40.    
  41.    
  42.    
  43.    
  44.    
  45.    
  46.    
  47.    
  48.    
  49.    
  50.                       Copyright 1989,1992 Dave Dunfield
  51.                              All rights reserved
  52.    Intro to MICRO-C                                                 Page: 1
  53.  
  54.  
  55.    1. INTRODUCTION
  56.    
  57.          Since releasing my MICRO-C compiler in 1988, I have received  many
  58.       requests to include information on the 'C' language as part  of  that
  59.       package.
  60.    
  61.          This manual is intended as a companion to  the  MICRO-C  compiler,
  62.       and presents an introduction to the 'C' language for  those  who  are
  63.       not already familiar  with  it.  The  language  represented  is  that
  64.       portion of 'C' which is implemented by the  MICRO-C  compiler.  Since
  65.       MICRO-C implements a  subset  of  the  'C'  programming  language  as
  66.       described by Kernighan and Ritchie (the original  developers  of  the
  67.       language), you should have little difficulty  using  and  learning  a
  68.       full 'C' compiler once you have mastered it.
  69.    
  70.          You should also refer to the  MICRO-C  technical  manual  entitled
  71.       "MICRO-C a compact 'C' compiler for small systems" for details on the
  72.       MICRO-C implementation.
  73.    
  74.          'C' has many inter-relationships between  its  various  constructs
  75.       and features. I have attempted to introduce them  in  a  logical  and
  76.       "building" manner,  however  it  is  not  always  possible  to  fully
  77.       describe each feature before it is mentioned in  the  description  of
  78.       some other construct. For this reason, I suggest that you  read  this
  79.       text "lightly from cover to cover" at least once before  you  try  to
  80.       fully understand each point.
  81.    
  82.          This is a first draft of this document. In its present form, it is
  83.       not very easy reading, but does contain much  useful  information.  I
  84.       will be improving and adding to it as I find the time.
  85.    
  86.          Presented herein is a brief summary of the major features  of  the
  87.       'C' language as implemented in MICRO-C.
  88.    Intro to MICRO-C                                                 Page: 2
  89.  
  90.  
  91.    2. BACKGROUND INFORMATION
  92.    
  93.          This section provides some detailed background information for the
  94.       novice, and may be skipped if  you  are  already  familier  with  the
  95.       basics of  computer  architecture  and  programming  languages.  This
  96.       information is presented  here  because  'C'  is  a  very  low  level
  97.       language, and an understanding of these basic  principals  will  help
  98.       you more easily understand how and why certain  constructs  work  the
  99.       way they do.
  100.    
  101.       2.1 Computer Architecture
  102.    
  103.             The basis of any computer system is its Central Processor  Unit
  104.          (CPU) which controls the operation  of  all  other  parts  of  the
  105.          computer, by following a set of "instructions"  which  make  up  a
  106.          software "program". The program is stored in "memory" and  directs
  107.          the CPU to read and write data  to  various  "peripheral"  devices
  108.          (Such as terminals, disks and printers), and  to  manipulate  that
  109.          data in a matter which accomplishes  the  goals  set  out  by  the
  110.          author of the program.
  111.    
  112.             Although there are a wide variety of CPUs available  in  modern
  113.          computers, they are all very similar, and  feature  the  following
  114.          characteristics:
  115.    
  116.             All data accessed by the CPU is represented by  circuits  which
  117.          may be either OFF or ON. This is represented by the digits  0  and
  118.          1. Since there are only two states (0 and 1), the computer may  be
  119.          thought of as operating in a BASE 2 (Binary)  number  system,  and
  120.          each individual data element is called a  Binary  digIT,  or  BIT.
  121.          This BASE 2 number system is used because it  is  much  easier  to
  122.          build and interface to electrical circuits  which  have  only  two
  123.          states (OFF and ON) than ones which have many states.
  124.    
  125.             Since  single   BITs   cannot   represent   much   information,
  126.          manipulating large amounts of data at the BIT  level  would  be  a
  127.          very tedious chore. For this reason, modern CPUs  access  data  as
  128.          groups of BITs. Usually the smallest group of data  which  can  be
  129.          manipulated by a computer consists of 8  BITs,  and  is  called  a
  130.          BinarY TErm (BYTE).
  131.    
  132.             Very small computers can often only access data a BYTE (8 bits)
  133.          at a time, while  larger  machines  may  be  able  to  access  and
  134.          manipulate data in larger groups called WORDS.  The  size  of  the
  135.          data group usually manipulated by a CPU is  called  its  WORDSIZE,
  136.          and is expressed in a number of bits.  This  is  almost  always  a
  137.          multiple of 8 bits, resulting in an even number of bytes. Thus, if
  138.          you hear a CPU or computer called a "16  bit"  machine,  you  know
  139.          that it can access and manipulate 16 bits (2 bytes) of data  at  a
  140.          time. A "32 bit" machine would operate on 32  bits  (4  bytes)  of
  141.          data. In general, the larger the WORDSIZE of a CPU, the more  data
  142.          it manipulates at one time, resulting in faster  completion  of  a
  143.          given task.
  144.    Intro to MICRO-C                                                 Page: 3
  145.  
  146.  
  147.             The CPU has access to external "memory", which consists of many
  148.          thousands (and often  millions)  of  WORDS  of  data.  Up  to  one
  149.          complete word of data may  be  transferred  between  the  CPU  and
  150.          memory in one memory access.
  151.    
  152.             Often it is known that each data element stored in memory  will
  153.          not take up an entire word, and is it desirable to  access  memory
  154.          in smaller groups, to reduce the number of memory  words  required
  155.          to accomplish a particular task. For this reason, most modern CPUs
  156.          can access any single BYTE (8 bits) from a memory word. It  should
  157.          be understood however, that accessing a single byte causes a  full
  158.          memory access, and takes just as much time as accessing an  entire
  159.          word.
  160.    
  161.             In order to provide the programmer  with  a  simple  method  of
  162.          specifying memory locations, each BYTE of memory  is  assigned  an
  163.          ADDRESS, which is simply the number of BYTES from the beginning of
  164.          memory to the desired byte. Therefore, the first  byte  in  memory
  165.          has address 0, the second byte byte in memory has address  1,  the
  166.          third byte has address 2 etc. Thus, memory from the  viewpoint  of
  167.          the programmer may be considered  as  a  simple  array  of  BYTES,
  168.          beginning with an address of 0,  and  continuing  with  sequential
  169.          addresses up the memory size (in bytes) of the computer.
  170.    
  171.             In addition to the external memory, a CPU has a small amount of
  172.          very fast internal memory which is  organized  into  words  called
  173.          "registers". Registers act as holding places  to  store  the  data
  174.          words which are to be manipulated. At least some of the  registers
  175.          are internally connected to an Arithmetic Logic Unit (ALU),  which
  176.          has the necessary electronics to perform basic operations such  as
  177.          addition and subtraction on  the  data  in  those  registers.  The
  178.          result of the operation is also placed in a register, often one of
  179.          the registers which contained the original data.
  180.    
  181.             One special register called the Program Counter (PC) is used by
  182.          the CPU to follow the software program. It contains the address of
  183.          the next INSTRUCTION to  be  executed.  At  the  beginning  of  an
  184.          INSTRUCTION CYCLE, the CPU reads the word of memory at the address
  185.          which is contained in the PC, and interprets the  value  contained
  186.          there as an operation to be performed, such as loading a  register
  187.          from memory, storing a register  into  memory,  or  performing  an
  188.          arithmetic operation  on  the  registers.  After  performing  that
  189.          operation, the CPU advances the PC to the next memory word  before
  190.          beginning another instruction cycle. In this manner,  all  of  the
  191.          instructions in a program are read, and the programmed  operations
  192.          are carried out.
  193.    
  194.             The CPU may also read from and  increment  the  PC  during  the
  195.          execution of an instruction, in order to access data  bytes  which
  196.          are OPERANDS to the particular instruction  being  executed.  Such
  197.          would be the case if you  were  instructing  the  CPU  to  load  a
  198.          register with the contents of a  particular  memory  address.  The
  199.          data bytes following the  instruction  would  contain  the  memory
  200.          address to be used.
  201.    Intro to MICRO-C                                                 Page: 4
  202.  
  203.  
  204.             There are a few instructions which direct the CPU  to  store  a
  205.          new value in the PC, rather than  advance  it.  These  are  called
  206.          JUMPS,  and  are  used  to  make  the  program   begin   executing
  207.          instuctions at a different address. This can  be  used  to  create
  208.          LOOPS in the program where a sequence of instructions is  executed
  209.          over and over again.
  210.    
  211.             Some of the "jump" instructions will only store the  new  value
  212.          in the PC if certain conditions are met,  such  as  the  last  ALU
  213.          operation resulted in zero, or did not result in zero. This allows
  214.          the program to alter  its  pattern  of  execution  based  on  data
  215.          values.
  216.    
  217.             For example, here is a program to count to 10 on a very  simple
  218.          imaginary computer. It shows the  use  of  IMMEDIATE  operands  to
  219.          instructions, which are shown by [PC+], and indicate  that  during
  220.          the execution of the instruction, the CPU  reads  the  next  value
  221.          from the address in the PC. The PC is advanced so that that  value
  222.          will not  be  executed  as  another  instruction  when  the  first
  223.          instruction is finished:
  224.    
  225.              Address   Interpretation of instruction value
  226.              ------------------------------------------------------
  227.                [0]     Load [PC+] data byte into register1
  228.                [1]     Data: 0
  229.                [2]     Add [PC+] data byte to register1
  230.                [3]     Data: 1
  231.                [4]     Load [PC+] data byte into register2
  232.                [5]     Data: 10
  233.                [6]     Subtract register1 from register2
  234.                [7]     Jump if result not zero to address in [PC+]
  235.                [8]     Data: 2
  236.                [9]     Halt CPU
  237.    Intro to MICRO-C                                                 Page: 5
  238.  
  239.  
  240.       2.2 Assembly Language
  241.    
  242.             In the preceeding section, you have learned how a CPU  executes
  243.          a program, and how a program may be coded in memory as a series of
  244.          instruction and data values. It should  be  obvious  to  you  that
  245.          although you can create programs in this way, it would be  a  long
  246.          and tedious job to write a program of any size using only  numeric
  247.          values.
  248.    
  249.             Not  only  is  it  very  hard  to  remember  the  hundreds   of
  250.          instruction  values  which  may  be  used   to   perform   certain
  251.          operations, but managing the memory address  which  are  coded  as
  252.          operands to the instructions becomes  a  real  headache.  This  is
  253.          particularily true when you  change  a  portion  of  the  program,
  254.          causing a change in the number of bytes of  memory  used  by  that
  255.          portion, and therefore  changes  all  of  the  memory  address  of
  256.          instructions and data which follow.
  257.    
  258.             To help ease the programming job, each of the CPU manufacturers
  259.          have defined an ASSEMBLY LANGUAGE for their CPU, which  represents
  260.          each of the machine operations with a more meaningful name  called
  261.          a MNEMONIC. Similar instructions may be  grouped  under  the  same
  262.          mnemonic with the individual instruction values determined by  the
  263.          operands.  For  example,  it  might  be  a  completely   different
  264.          instruction value which loads Register1 with  a  value  than  that
  265.          which loads register2. In assembly language you would use  similar
  266.          statements such as:
  267.    
  268.                LOAD R1,10
  269.                LOAD R2,10
  270.    
  271.             The  translation  from  mnemonics  to  instruction  values   is
  272.          performed by  a  program  called  an  ASSEMBLER.  In  addition  to
  273.          performing this translation, the assembler also allows LABEL names
  274.          to be assigned to addresses. The labels may be  referred  to  from
  275.          within other assembly  language  statements  instead  of  absolute
  276.          addresses.
  277.    
  278.             When written in assembly language, our "count  to  10"  program
  279.          would look something line this:
  280.    
  281.                    LOAD    R1,0
  282.            LOOP:   ADD     R1,1
  283.                    LOAD    R2,10
  284.                    SUB     R2,R1
  285.                    JMPNZ   LOOP
  286.                    HALT
  287.    
  288.             As  you  can  see,  the  above  program  would  be  much   more
  289.          understandable than a series of  numbers,  but  it  is  still  not
  290.          obvious to someone other that the author what the  intent  of  the
  291.          program is until he has followed through the loop, and  determined
  292.          what is accomplished by each instruction.
  293.    Intro to MICRO-C                                                 Page: 6
  294.  
  295.  
  296.             Imagine that you have just started a  new  job  as  a  computer
  297.          programmer, and your  manager  hands  you  a  listing  of  several
  298.          hundred pages, each of which is full of  assembly  language  lines
  299.          looking like the example  above,  and  says  "The  'SCAN'  command
  300.          causes corruption of the database search parameters. This is  VERY
  301.          important, could you stay and fix it tonight". You would have many
  302.          hours  (days?)  ahead  of  you  trying  to   determine   what   is
  303.          accomplished by each portion of the program. Now, imagine that the
  304.          assembly language looked more like this:
  305.    
  306.            ;
  307.            ; Simple demonstration program to count from 0 to 9
  308.            ;
  309.                    LOAD    R1,0        ; Begin with count of zero
  310.            ; Execute this loop once for each count
  311.            COUNT:  ADD     R1,1        ; Increment count
  312.                    LOAD    R2,10       ; Loop termination value
  313.                    SUB     R2,R1       ; Test R1, (result destroys R2)
  314.                    JMPNZ   COUNT       ; Repeat until we reach 10
  315.            ; We have reached 10 - All done
  316.                    HALT                ; Stop processing
  317.    
  318.             The text statements following the ';' characters in  the  above
  319.          example are called COMMENTS. They are completely  ignored  by  the
  320.          assembler, but are very useful to anyone attempting to  understand
  321.          the program.
  322.    
  323.       2.3 High Level Languages
  324.    
  325.             As you can see in the  preceeding  section,  assembly  language
  326.          programming offers much of  an  improvement  over  programming  by
  327.          direct instruction  values,  while  retaining  the  capability  to
  328.          control  EXACTLY  the  individual  operations  the  program   will
  329.          instruct the CPU to perform. Also, since the assembly language for
  330.          a particular CPU is defined by the manufacturer, you can  be  sure
  331.          that using it will allow you to take advantage  of  EVERY  feature
  332.          and capability that has been designed  into  that  particular  CPU
  333.          architecture.
  334.    
  335.             A good assembly language programmer can produce highly efficent
  336.          and compact programs because of this power. For  this  reason  you
  337.          will often see assembly  language  used  for  very  time  or  size
  338.          intensive applications.
  339.    Intro to MICRO-C                                                 Page: 7
  340.  
  341.  
  342.             It would seem that assembly language would be the ideal  method
  343.          of  doing  all  your  programming.  There  are  however,   several
  344.          drawbacks to using assembly language:
  345.    
  346.          1) Efficent use of assembly language often requires a  "different"
  347.             way of  looking  at  a  problem  and  strong  "logical"  mental
  348.             dicipline.
  349.             ** Not everyone is a good assembly language programmer **
  350.    
  351.          2) Assembly language source files are big.
  352.             ** It takes much codeing to perform even simple operations **
  353.             ** Significant time is spent entering source text **
  354.             ** Greater chance of error during design and entry **
  355.    
  356.          3) Poorly documented assembly language is undecipherable.
  357.             ** It is hard to maintain **
  358.    
  359.          4) Each assembly language is different and incompatible.
  360.             ** Programs will run on only one type of CPU **
  361.             ** Programmers have difficulty working on other CPUs **
  362.    
  363.             To help solve these problems,  there  are  a  number  of  "high
  364.          level"  programming  languages  available.  The  main   difference
  365.          between  assembly  and  high  level  languages  is  that  assembly
  366.          language produces only  one  CPU  instruction  for  each  language
  367.          "statement",  while  high  level  languages   can   produce   many
  368.          instructions for each "statement".
  369.    
  370.             High level languages attempt to provide a method of programming
  371.          by expressing ideas, rather than by directing the CPU  to  perform
  372.          each individual operation. When using a high level  language,  you
  373.          are freed from the task of keeping track of  register  and  memory
  374.          usage, and can concentrate  on  expressing  the  algorithms  which
  375.          accomplish the goal of the program.
  376.    
  377.             Here are some "high  level"  versions  of  our  "count  to  10"
  378.          program:
  379.    
  380.    
  381.        Basic:      100 FOR I=0 TO 10:NEXT I
  382.    
  383.        Fortran:        DO 100 i=0,10
  384.                    100 CONTINUE
  385.    
  386.        Forth:      11 0 DO LOOP
  387.    
  388.        'C':        for(i=0; i <= 10; ++i);
  389.    Intro to MICRO-C                                                 Page: 8
  390.  
  391.  
  392.       2.4 Interpreters VS Compilers
  393.    
  394.             There  are   two   basic   types   of   high   level   language
  395.          implementations, INTERPRETERS and COMPILERS.
  396.    
  397.             An INTERPRETER is a program which reads  your  source  program,
  398.          and performs the actions indicated by  its  statements.  The  main
  399.          advantages to this approach are:
  400.    
  401.          1) FAST DEVELOPMENT:  Interpreters  often  include  complete  text
  402.             editors, which make it easy to  edit  and  debug  your  program
  403.             without leaving the interpreter. Also,  since  the  program  is
  404.             interpreted  directly,  there  is  no  waiting  to  compile  or
  405.             assemble it before you can try out a new change.
  406.    
  407.          2) EASY DEBUGGING:  Since  the  interpreter  is  actually  another
  408.             program, it will usually allow you to stop your program in  the
  409.             middle of execution, examine/modify  variables,  trace  program
  410.             flow, display callback stacks, etc. This makes  for  very  easy
  411.             debugging. Also, a good interpreter will perform  very  through
  412.             checking of your program as it interpretes,  thus  finding  and
  413.             reporting design errors which might otherwise show up  only  as
  414.             erratic and inconsistant program operation.
  415.    
  416.             And of course, there are drawbacks to interpreting:
  417.    
  418.          1) SLOW EXECUTION: The interpreter has to process  each  statement
  419.             in your program and determine what action is  to  be  performed
  420.             every time it encounters that statement. Many hundreds or  even
  421.             thousands of instructions are executed to accomplish  this  FOR
  422.             EACH STATEMENT.
  423.    
  424.          2) USES MEMORY: A good interpreter is a  fairly  complex  program,
  425.             and therefore occupies a substantial portion of system  memory,
  426.             meaning that less is available for your program & variables.
  427.    
  428.          3) DIFFICULTY OF USE: Once you are finished debugging,  you  would
  429.             like to  make  your  program,  as  easy  to  use  as  possible.
  430.             Unfortunatly, when using an interpreter,  you  always  have  to
  431.             load and execute the interpreter before loading  and  executing
  432.             your program.
  433.    
  434.             These disadvantages are so severe that interpreters are  rarely
  435.          used for serious programs which are to be  used  frequently  by  a
  436.          number of people. They are however, excellent learning  tools  for
  437.          the novice computer user.
  438.    Intro to MICRO-C                                                 Page: 9
  439.  
  440.  
  441.             A COMPILER is a program which reads your  source  program,  and
  442.          translates its statements into CPU INSTRUCTIONS which perform  the
  443.          specified function. Instead of actually executing your program, it
  444.          converts it to a form which can later be directly executed by  the
  445.          CPU. Its main advantages are:
  446.    
  447.          1) FAST EXECUTION: Since the program will be executed directly  by
  448.             the CPU, it will run much faster that  the  equivalent  program
  449.             being translated by an interpreter.
  450.    
  451.          2) LESS MEMORY: Although a compiler is a very complex program, and
  452.             uses lots of memory when it runs,  it  only  runs  once,  after
  453.             which your program is executed by itself directly by  the  CPU.
  454.             This means that the amount of memory required by  the  compiler
  455.             does not affect the amount of memory which is available for use
  456.             by your program when it runs.
  457.    
  458.          3) EASE OF USE: Since your program executes  by  itself,  you  can
  459.             load and execute it directly from the operating system  command
  460.             prompt.
  461.    
  462.             The main disadvantages of compilers over interpreters are:
  463.    
  464.          1) LONGER DEVELOPMENT: Many "traditional" compilers  require  that
  465.             you prepare your source program using a  separate  editor,  and
  466.             then save it to a disk  file,  and  submit  that  file  to  the
  467.             compiler. Every time you do this, you  have  to  wait  for  the
  468.             compiler to finish before you can even try your program.  NOTE:
  469.             some compiler vendors are  now  providing  integrated  editors,
  470.             eliminating the "save and exit" step, however you may not  like
  471.             the editor they have chosen for you.
  472.    
  473.          2) MORE  DIFFICULT  DEBUGGING:  Since  your  program  executes  by
  474.             itself, you have to run a standard system debugger  to  monitor
  475.             its execution. This will usually  be  somewhat  less  intuitive
  476.             than an interpreters built in debugging  features.  NOTE:  some
  477.             compiler  vendors  provide  a  "debug"  option  which  includes
  478.             debugging information in the program, and  a  special  debugger
  479.             which provides debugging facilities equal  to  or  better  than
  480.             those available from most interpreters.
  481.    
  482.       2.5 Object Modules & Linking
  483.    
  484.             Most assemblers and compilers available today support  the  use
  485.          of a LINKER. The linker is a program which  will  combine  several
  486.          previously compiled (or assembled) programs called OBJECT  MODULES
  487.          into a single larger executable  program.  This  helps  speed  the
  488.          development process by eliminating  the  need  to  re-compile  the
  489.          entire program when you have changed only one module.
  490.    Intro to MICRO-C                                                 Page: 10
  491.  
  492.  
  493.       2.6 Compiler Libraries
  494.    
  495.             Modern compilers promote  the  use  of  STRUCTURED  PROGRAMMING
  496.          techniques, which make programs easier to debug and maintain. I do
  497.          not propose to get into a  discussion  of  structured  programming
  498.          methods, but the main idea is to divide the  program  into  simple
  499.          parts, each of which performs a clearly defined function.
  500.    
  501.             Such functions often perform common algorithms required by many
  502.          programs, and  hence  are  made  into  compiler  LIBRARIES.  These
  503.          libraries are simply collections of small  useful  programs  which
  504.          may be used from within your programs without you having to  write
  505.          them. Most compiler manufacturers  provide  such  a  "library"  of
  506.          functions which they  believe  to  be  commonly  needed,  and  the
  507.          development tools necessary to link them with your programs.
  508.    
  509.       2.7 Portability
  510.    
  511.             One BIG advantage of high level languages is the fact that once
  512.          a program is written and running on one CPU, you can  usually  get
  513.          it  running  on  another  completely  different  CPU  with  little
  514.          difficulty. This is because although the CPUs are  different,  the
  515.          HIGH LEVEL LANGUAGE IS NOT CPU DEPENDANT AND REMAINS THE SAME. All
  516.          you have to do is to re-compile your  program,  using  a  compiler
  517.          which produces code for the new CPU.
  518.    
  519.             Actually, it usually takes a bit more effort than that, because
  520.          the language or library functions may  differ  slightly  from  one
  521.          implementation to another.
  522.    
  523.             This concept of PORTABILITY is one of the strong points of  the
  524.          'C' language, and you will see it  mentioned  from  time  to  time
  525.          throughout  this  manual.  In  addition  to  consistant   compiler
  526.          language implementation, 'C' benefits from very "standard" library
  527.          function definitions which are followed by most vendors.
  528.    Intro to MICRO-C                                                 Page: 11
  529.  
  530.  
  531.    3. INTRODUCTION TO 'C'
  532.    
  533.          'C' is a "high level" computer language,  which  has  become  very
  534.       popular in recent years. It has proven suitable for a  large  variety
  535.       of programming tasks, and unlike most other high level languages,  is
  536.       quite good for "low  level"  and  "system"  type  functions.  A  good
  537.       example of this capability is the popular  "UNIX"  operating  system,
  538.       which is  written  almost  entirely  in  'C'.  Before  UNIX,  it  was
  539.       generally thought that only assembly language was efficent enough for
  540.       writing an operating system.
  541.    
  542.          Programs in 'C' are divided into two main parts, VARIABLES,  which
  543.       are blocks of memory reserved for storing data, and FUNCTIONS,  which
  544.       are blocks of memory containing executable CPU instructions. They are
  545.       created using a DECLARATION STATEMENT, which is basically  a  command
  546.       to the compiler telling it what type of variable or function you wish
  547.       to create, and what values or instructions to place in it.
  548.    
  549.          There are several 'C' KEYWORDS which serve to inform the  compiler
  550.       of the size and type of a variable or function. This  information  is
  551.       used by the compiler to determine how to interpret the  value  STORED
  552.       in a VARIABLE, or RETURNED by a FUNCTION.
  553.    
  554.        Size:   int         - 16 bit value (default)
  555.                char        - 8 bit value
  556.        type:   unsigned    - Positive only (0-2**bits)
  557.                            + Default is signed (positive & negative)
  558.    
  559.        Examples:   int a;              /* 16 bit signed variable */
  560.                    char b;             /* 8 bit signed variable */
  561.                    unsigned int c;     /* 16 bit unsigned variable */
  562.                    unsigned d;         /* Also 16 bit unsigned variable */
  563.                    unsigned char e;    /* 8 bit unsigned variable */
  564.    
  565.          Normally, when you define a function or global variable, its  name
  566.       is made accessable to all object modules which will  be  linked  with
  567.       the program. You may access a  name  which  is  declared  in  another
  568.       module by  declaring  it  in  this  module  with  with  the  "extern"
  569.       modifier:
  570.    
  571.           extern int a;       /* external variable of type int    */
  572.           extern char b();    /* external function returning char */
  573.    
  574.          If you want to make sure that a function or global  variable  that
  575.       you are declaring is not accessable to  another  module  (To  prevent
  576.       conflicts with names in other modules etc), you can declare  it  with
  577.       the "static" modifier. This causes the name to be accessable only  by
  578.       functions within the module containing the "static" declaration:
  579.    
  580.                                 static int a;
  581.    Intro to MICRO-C                                                 Page: 12
  582.  
  583.  
  584.       3.1 Functions
  585.    
  586.             FUNCTIONS in 'C' are  collections  of  C  language  STATEMENTS,
  587.          which are grouped together under a name. Each statement represents
  588.          an operation which is to be performed by the CPU. For example, the
  589.          statement:
  590.    
  591.                                   A = A + 1;
  592.    
  593.          directs the CPU to read the variable called 'A', add a value of  1
  594.          to it, and to store the result back into the variable  'A'  (we'll
  595.          discuss variables in the next section). Note the  SEMICOLON  (';')
  596.          at the end  of  the  statement.  The  'C'  compiler  uses  ';'  to
  597.          determine when the statement ends. It does not care about lines or
  598.          spaces. For example, the above statement could also be written:
  599.    
  600.                                       A
  601.                                       =
  602.                                       A
  603.                                       +
  604.                                       1
  605.                                       ;
  606.    
  607.          and would still compile without error. Thus, you can have  a  VERY
  608.          long statement in 'C', which spans several lines. You must  always
  609.          however, be very careful to include the terminating ';'.
  610.    
  611.             Each function within a 'C' program can be "called" by using its
  612.          name in any statement, may accept "argument" values which  can  be
  613.          accessed by the statements contained within it, and may  return  a
  614.          value back to the caller. This allows functions in 'C' to be  used
  615.          as "building blocks", providing extensions to the language,  which
  616.          may be used from any other function.
  617.    
  618.             Below is a sample 'C' function,  which  performs  an  operation
  619.          (addition) on two argument values. The text between '/*' and  '*/'
  620.          is COMMENTS, and is ignored by the compiler.
  621.    
  622.            /* Sample 'C' function to add two numbers */
  623.            int add(num1, num2)     /* Declaration for function */
  624.                int num1, num2;     /* Declaration for arguments */
  625.            {
  626.                return num1+num2;   /* Send back sum of num1 and num2 */
  627.            }
  628.    
  629.             The names located within the  round  brackets  '()'  after  the
  630.          function name "add" tells the compiler what names you want to  use
  631.          to refer to the ARGUMENT VALUES. The "return" statement  tell  the
  632.          compiler that you want to terminate the execution of the function,
  633.          and return the value of  the  following  expression  back  to  the
  634.          caller. (We'll discuss "return" in more detail later).
  635.    Intro to MICRO-C                                                 Page: 13
  636.  
  637.  
  638.             Now that you have defined the function "add", you could use  it
  639.          in any other statement, in any function in your program, simply by
  640.          calling it with its name and argument values:
  641.    
  642.                                 a = add(1, 2);
  643.    
  644.             The above statement would call "add", and pass  it  the  values
  645.          '1' and '2' as arguments. "add" evaluates 1  +  2  to  be  3,  and
  646.          returns that value back, which is then stored in the variable 'a'.
  647.    
  648.             Note that 'C' uses the  round  brackets  following  a  name  to
  649.          determine that you wish to call the function, therefore, even if a
  650.          function has no argument values, you must include '()':
  651.    
  652.                                a = function();
  653.    
  654.             Also note, that if a function does not return a value,  or  you
  655.          do not want to  use  the  returned  value,  you  simply  code  the
  656.          function name by itself:
  657.    
  658.                                  function();
  659.    
  660.       3.2 Variables
  661.    
  662.             VARIABLES in 'C' are reserved areas of memory  where  the  data
  663.          manipulated by the program is stored. Each variable is assigned  a
  664.          name by which it  is  referenced  by  other  'C'  statements.  ALL
  665.          VARIABLES IN 'C' MUST BE DECLARED.
  666.    
  667.             Variables in 'C' may be single values as shown eariler, or they
  668.          may be declared as an ARRAY, which reserves  memory  space  for  a
  669.          number of data elements, each  with  the  type  declared  for  the
  670.          variable.
  671.    
  672.                                 int array[4];
  673.    
  674.             The above statement reserves memory  for  four  16  bit  signed
  675.          values, under the name "array". It is important to know  that  'C'
  676.          considers the elements of an array to be numbered from  zero  (0),
  677.          so the four locations in the above array are referenced by using:
  678.    
  679.                                    array[0]
  680.                                    array[1]
  681.                                    array[2]
  682.                                    array[3]
  683.    
  684.             There are two basic types  of  variables  in  'C',  GLOBAL  and
  685.          LOCAL.
  686.    Intro to MICRO-C                                                 Page: 14
  687.  
  688.  
  689.          3.2.1 GLOBAL Variables
  690.    
  691.                GLOBAL variables are set up permanently in memory, and exist
  692.             for the duration of the entire programs execution. The names of
  693.             global variables may be referenced by  any  statement,  in  any
  694.             function, at any time. Global variables are declared in 'C'  by
  695.             placing the declaration statement OUTSIDE of any function.  For
  696.             example:
  697.    
  698.                int a;      /* Declare GLOBAL variable */
  699.    
  700.                inita()     /* Function to initialize 'a' with 1 */
  701.                {
  702.                    a = 1;
  703.                }
  704.    
  705.                Note that the declaration statement for 'a' is NOT contained
  706.             within the definition of "inita".
  707.    
  708.                Since global variables are permanent blocks of memory, it is
  709.             possible to INITIALIZE them in the declaration statement.  This
  710.             causes the variable to be assigned a  value  at  COMPILE  time,
  711.             which will be loaded into memory at  the  same  time  that  the
  712.             program is loaded to be executed. This means that your  program
  713.             will not have to explicitly store a value in a.
  714.    
  715.                                   int a = 1;
  716.    
  717.                Array variables may also be initialized in  the  declaration
  718.             statement, by using the  curly  brackets  '{}'  to  inform  the
  719.             compiler that you have multiple values:
  720.    
  721.                           int a[4] = { 1, 2, 3, 4 };
  722.    
  723.                In MICRO-C, the initial values for an array are expressed as
  724.             a single string of values  REGUARDLESS  of  the  shape  of  the
  725.             array:
  726.    
  727.                         int a[2][2] = { 1, 2, 3, 4 };
  728.    
  729.                If an array has only one dimension (set of  '[]'s),  you  do
  730.             not have to specify the  size  of  initialized  variables.  The
  731.             compiler will automatically set  the  size  to  the  number  of
  732.             initial values given:
  733.    
  734.                         int array[] = { 1, 2, 3, 4 };
  735.    Intro to MICRO-C                                                 Page: 15
  736.  
  737.  
  738.          3.2.2 LOCAL Variables
  739.    
  740.                Variables  which  are  declared  WITHIN   a   function   are
  741.             determined by the compiler to be  LOCAL.  The  memory  used  by
  742.             these variables is automatically  reserved  when  the  function
  743.             begins to execute, and is released when it terminates. Names of
  744.             LOCAL variables are only accessable from  within  the  function
  745.             where they are defined:
  746.    
  747.                inita()     /* Function to initialize 'a' with 1 */
  748.                {
  749.                    int a;  /* Declare LOCAL variable */
  750.    
  751.                    a = 1;
  752.                }
  753.    
  754.                The  above  function  shows  the  declaration  of  a   local
  755.             variable, but is not very useful since the local variable  will
  756.             cease to exist when the function returns. Local  variables  are
  757.             used as temporary locations  for  holding  intermediate  values
  758.             created during a functions execution, which are not required by
  759.             any other part of the program.
  760.    
  761.                Each function may have its own local  variables,  but  since
  762.             memory is  only  used  by  the  functions  which  are  actually
  763.             executing, the total amount of memory reserved is usually  less
  764.             that the total size of all local variables in the program.
  765.    
  766.                Since local variables are allocated and released during  the
  767.             execution of your program, it is  not  possible  to  initialize
  768.             them at compile time, and therefore MICRO-C does not allow them
  769.             to be initialized in the declaration. Some compilers  do  allow
  770.             this, however,  the  code  generated  is  equivalent  to  using
  771.             assignment statements to initialize them at  the  beginning  of
  772.             the function.
  773.    
  774.                The ARGUMENTS to a function  (See  Functions)  are  actually
  775.             local variables for that function which are  created  when  the
  776.             function is called. For this reason,  the  argument  names  are
  777.             also un-available outside of the function  in  which  they  are
  778.             defined.
  779.    Intro to MICRO-C                                                 Page: 16
  780.  
  781.  
  782.       3.3 Pointers
  783.    
  784.             A POINTER in 'C' is a memory address,  which  can  be  used  to
  785.          access another data item in memory. All pointers in MICRO-C are 16
  786.          bit values, which allows access to a maximum  of  65536  bytes  of
  787.          memory through it.
  788.    
  789.             Any variable or function  may  be  declared  as  a  pointer  by
  790.          preceeding its name with the '*' character in the declaration:
  791.    
  792.            int *a;                 /* a = 16 bit pointer to int value */
  793.            char *b;                /* b = 16 bit pointer to char */
  794.            extern char *fgets();   /* Returns 16 bit pointer to char */
  795.    
  796.             Later on, I will show you how you can use  a  special  operator
  797.          called INDIRECTION to access data items at the  address  contained
  798.          in the pointer.
  799.    
  800.       3.4 A complete 'C' program
  801.    
  802.             With all of the preceeding  information  under  you  belt,  you
  803.          should be able to understand most  of  this  simple  but  complete
  804.          program:
  805.    
  806.            #include stdio.h
  807.    
  808.            /* Main program */
  809.            main()
  810.            {
  811.                int a, b, c;
  812.    
  813.                a = 1;
  814.                b = 2;
  815.                c = add(a, b);
  816.                printf("The result of (1+2)=%d\n", c);
  817.            }
  818.    
  819.            /* Our old familiar "add" function */
  820.            int add(num1, num2)
  821.                int num1, num2;
  822.            {
  823.                return num1+num2;
  824.            }
  825.    
  826.             Did you fully understand it??? ... I thought not!!!
  827.    
  828.             There are a few new things presented in this program,  which  I
  829.          will now explain.
  830.    
  831.             First of all, you should know that the function name "main"  is
  832.          a special name which will be called at the  very  beginning,  when
  833.          the program is first run. It provides a starting  point  for  your
  834.          programmed functions. All 'C' programs have a "main" function.
  835.    Intro to MICRO-C                                                 Page: 17
  836.  
  837.  
  838.             You may also be wondering about those "#include"  and  "printf"
  839.          statements. This all comes back to the concept of PORTABILITY, and
  840.          has to do with the programs ability to perform  INPUT  and  OUTPUT
  841.          (I/O). Methods of performing  I/O  may  differ  greatly  from  one
  842.          operating system to another, and hence make it difficult to  write
  843.          "portable" programs. If you don't know  what  portability  is,  go
  844.          back and read the "Background Information" section.
  845.    
  846.             In order to insure that 'C' compilers could be  easily  adapted
  847.          to nearly any operating system,  the  designers  of  the  language
  848.          decided not to  include  ANY  I/O  capabilities  in  the  compiler
  849.          itself. By not implementing it, they didn't have  to  worry  about
  850.          it. All such activity is performed by a set of  functions  in  the
  851.          'C' STANDARD LIBRARY, which is provided for each operating system.
  852.    
  853.             These library functions are used in nearly all programs,  since
  854.          a program which can't read or  write  any  data  doesn't  do  much
  855.          useful work.
  856.    
  857.             Many of the library functions must be  declared  as  a  certain
  858.          type, which may be specific  to  the  compiler  implementation  or
  859.          operating system. (For example  the  "printf"  functions  must  be
  860.          declared as "register" in MICRO-C). The file "stdio.h" is provided
  861.          with  all  "standard  libraries",   and   contains   any   special
  862.          declarations required by the library functions.
  863.    
  864.             The "#include"  statement  causes  the  compiler  to  read  the
  865.          "stdio.h"  file,  and  to  process  the   declaration   statements
  866.          contained within it. This is equivalent to incorporating the  full
  867.          text of "stdio.h" at the beginning of your program.
  868.    
  869.             The "printf" statement is actually a call to a STANDARD LIBRARY
  870.          FUNCTION. It is available in almost all 'C'  implementations,  and
  871.          in the above example, displays the prompt "The result of  (1+2)=",
  872.          followed by the decimal value of the passed argument 'c'. For more
  873.          information about "printf" and other library functions,  refer  to
  874.          the MICRO-C Technical manual.
  875.    
  876.             At his point you may wish to enter  the  demonstration  program
  877.          into a file called "DEMO1.C", and  compile  it  with  the  MICRO-C
  878.          compiler. Remember that 'C' IS CASE SENSITIVE, so be sure to enter
  879.          the program EXACTLY as it is shown. Also, make sure that  you  are
  880.          positioned in the MICRO-C directory before you  create  the  file.
  881.          After entering and saving the file with your favorite text editor,
  882.          compile the program using the command:
  883.    
  884.                                   CC86 DEMO1
  885.    
  886.             You can  run  the  resultant  "DEMO1.COM"  program,  by  simply
  887.          typeing "DEMO1", at the DOS command prompt.
  888.    Intro to MICRO-C                                                 Page: 18
  889.  
  890.  
  891.       3.5 'C' memory organization
  892.    
  893.             Now that you have seen a complete 'C'  program,  and  know  the
  894.          basic concepts of functions and variables, you may  want  to  know
  895.          how MICRO-C organizes the computer memory  when  these  constructs
  896.          are used. Knowing this  may  help  you  understand  functions  and
  897.          variables more precicely.
  898.    
  899.             The information in this section is  not  really  necessary  for
  900.          casual use of the language, if you feel  that  such  detail  would
  901.          only confuse you, feel free to skip it until later.
  902.    
  903.             The MICRO-C compiler builds your program to occupy a  block  of
  904.          memory. In the case of small 8 bit computers, this block of memory
  905.          will usually be the entire free ram in the machine. In the case of
  906.          larger machines, it will usually be 64K (65536 bytes), but may  be
  907.          larger or smaller depending on the implementation.
  908.    
  909.             The exact size of the memory block  is  unimportant,  since  it
  910.          affects only the maximum size of a MICRO-C program. The methods of
  911.          memory allocation remain the same.
  912.    
  913.          3.5.1 Static memory
  914.    
  915.                MICRO-C places all of the executable code from the  compiled
  916.             functions at the very  beginning  of  the  memory  block.  This
  917.             includes all  CPU  instructions  which  are  generated  by  the
  918.             compiler. MICRO-C places all initialized  global  variables  in
  919.             this area as well, and also something called the LITERAL POOL.
  920.    
  921.                The "literal pool" consists of all string data which is used
  922.             in statements or initializations in the program. An example  of
  923.             this is the string used in the preceeding demonstration program
  924.             ("Result of (1+2)=%d\n"), which is  a  series  of  data  bytes,
  925.             which are passed to the "printf" function.
  926.    
  927.                This collection of CPU  instructions,  Initialized  variable
  928.             data, and literal pool data is the complete program image which
  929.             must be loaded into memory every time the program is executed.
  930.    
  931.                The next section of memory allocated by  MICRO-C  holds  the
  932.             global variables which have not been  initialized.  Since  they
  933.             have no initial values, they do not have  to  be  loaded  every
  934.             time the program runs. This also means that until  the  program
  935.             stores a value in a particular  memory  location  its  contents
  936.             will be some random value which happened to be at that location
  937.             in memory before the program was loaded.
  938.    
  939.                All of this memory is called "STATIC" memory, because it  is
  940.             reserved for code and data at COMPILE time. Once the program is
  941.             compiled, the above mentioned items are fixed  in  memory,  and
  942.             cannot be moved or changed in size.
  943.    Intro to MICRO-C                                                 Page: 19
  944.  
  945.  
  946.          3.5.2 Dynamic memory
  947.    
  948.                When your program begins execution, one of the first  things
  949.             that happems, is that a STACK is set up at the very top of  the
  950.             memory block. This  stack  is  always  referenced  by  a  STACK
  951.             POINTER register which always points to the lowest  address  of
  952.             memory used on the stack. All memory in  the  block  above  the
  953.             stack pointer is deemed to be in use. This is usually  a  built
  954.             in feature of the CPU.
  955.    
  956.                At the beginning of every function,  the  code  produced  by
  957.             MICRO-C contains instructions to reduce the value of the  stack
  958.             pointer by the number of bytes of memory required by the  local
  959.             variables in that function.  When  the  function  "returns"  or
  960.             terminates, the stack pointer is increased by the same amount.
  961.    
  962.                This allows the function to use the memory immediatly  above
  963.             the new stack pointer for its local variables without fear that
  964.             another function will also try to use it. When another function
  965.             is called, it will reserve its memory BELOW the memory  already
  966.             in use by the calling  function,  and  will  return  the  stack
  967.             pointer when it is finished. Thus, all local variables  may  be
  968.             accessed as constant offsets from the stack pointer set  up  at
  969.             the beginning of the function.
  970.    
  971.                ARGUMENTS to a function are passed by  reserving  memory  on
  972.             the stack, and setting it to the argument values, just PRIOR to
  973.             calling the function. When the  called  function  returns,  the
  974.             stack reserved for its arguments is  removed  by  the  function
  975.             performing the call. In this way, the arguments are  just  more
  976.             local variables, and may also be accessed as  constant  offsets
  977.             from the stack pointer.
  978.    
  979.          3.5.3 Heap memory
  980.    
  981.                Some programs need temporary memory which will not disappear
  982.             when the function terminates, or they may not  know  the  exact
  983.             amount of memory they need for a certain operations until  some
  984.             calculations have been performed.
  985.    
  986.                To resolve these problems,  'C'  provides  another  type  of
  987.             dynamic memory which is called "HEAP" memory. To  make  use  of
  988.             this memory, the program uses the "malloc" function  (from  the
  989.             standard library)  which  allocates  a  block  of  memory,  and
  990.             returns a pointer value to its address. The  program  may  then
  991.             access and manipulate this memory through the pointer.
  992.    
  993.                When the program is finished with the memory,  it  may  then
  994.             use the "free" library function to  release  it,  and  make  it
  995.             available for use by other calls to "malloc".
  996.    
  997.                A program may continue allocating  memory  via  "malloc"  as
  998.             long as there is available free memory to allocate. The library
  999.             functions will  keep  track  of  which  blocks  of  memory  are
  1000.             allocated, and which blocks are available for allocation.
  1001.    Intro to MICRO-C                                                 Page: 20
  1002.  
  1003.  
  1004.                A typical memory layout for a 'C' program in the  middle  of
  1005.             execution might look something like this:
  1006.    
  1007.                +----------------------------------------+
  1008.                |            CPU Instructions            |
  1009.                |         which make up program          |
  1010.                |                "code"                  |
  1011.                +----------------------------------------+
  1012.                |      Initialized GLOBAL variables      |
  1013.                +----------------------------------------+
  1014.                |           LITERAL POOL data            |
  1015.                +----------------------------------------+
  1016.                |    Un-initialized GLOBAL variables     |
  1017.                +----------------------------------------+
  1018.                |      Memory allocated to the heap      |
  1019.                +----------------------------------------+
  1020.                |          (Heap grows upward)           |
  1021.                |                   |                    |
  1022.                |  Free memory, available for growth of  |
  1023.                |           the heap and stack.          |
  1024.                |                   |                    |
  1025.                |         (Stack grows downward)         |
  1026.                +----------------------------------------+
  1027.                |  Local variables of innermost function |
  1028.                +----------------------------------------+
  1029.                |  Return address of innermost function  |
  1030.                +----------------------------------------+
  1031.                |     Arguments of innermost function    |
  1032.                +----------------------------------------+
  1033.                |  Local variables of middle function    |
  1034.                +----------------------------------------+
  1035.                |   Return address of middle function    |
  1036.                +----------------------------------------+
  1037.                |      Arguments of middle function      |
  1038.                +----------------------------------------+
  1039.                |    Local variables of main function    |
  1040.                +----------------------------------------+
  1041.                |    Return address of main function     |
  1042.                +----------------------------------------+
  1043.    
  1044.                For those  not  familiar  with  computer  architecture,  the
  1045.             RETURN ADDRESS is placed on the stack by  a  CALL  INSTRUCTION,
  1046.             and  is  the  memory   address   immediately   following   that
  1047.             instruction. When a RETURN INSTRUCTION is later  executed,  the
  1048.             CPU removes the return address from the stack, and places it in
  1049.             the PROGRAM COUNTER, thus causing program execution  to  resume
  1050.             with the instruction immediately following  the  original  call
  1051.             instruction.
  1052.    Intro to MICRO-C                                                 Page: 21
  1053.  
  1054.  
  1055.    4. EXPRESSIONS
  1056.    
  1057.          An expression in 'C' consists of one or more values, and OPERATORS
  1058.       which cause those values to be modified in  a  calculation.  Anywhere
  1059.       that you would use a simple  value  in  'C',  you  can  also  use  an
  1060.       expression. We have already seen that with the "return" statement  in
  1061.       the "add" function in our example program. Knowing that  we  can  use
  1062.       expressions and values interchangably, we could shorten  the  example
  1063.       "main" function to:
  1064.    
  1065.            main()
  1066.            {
  1067.                int a, b;
  1068.    
  1069.                a = 1;
  1070.                b = 2;
  1071.                printf("The result of (1+2)=%d\n", add(a,b));
  1072.            }
  1073.    
  1074.        or even:
  1075.    
  1076.            main()
  1077.            {
  1078.                int a, b;
  1079.    
  1080.                a = 1;
  1081.                b = 2;
  1082.                printf("The result of (1+2)=%d\n", a+b);
  1083.            }
  1084.    
  1085.        or even:
  1086.    
  1087.            main()
  1088.            {
  1089.                printf("The result of (1+2)=%d\n", 1 + 2);
  1090.            }
  1091.    
  1092.        Or, if we wanted the 'a, b & c' variables set anyway:
  1093.    
  1094.            /* Note the use or round brackets '()' to incorporate
  1095.               a SUB-EXPRESSION into the main expression */
  1096.            main()
  1097.            {
  1098.                int a, b, c;
  1099.    
  1100.                printf("The result of (1+2)=%d\n", c = (a = 1) + (b = 2));
  1101.            }
  1102.    
  1103.          You can see that an entire expression, including three ASSIGNMENTS
  1104.       was included in a place where only a simple value is  used.  This  is
  1105.       one of the great powers of 'C', and can result  in  very  small  fast
  1106.       efficent code (at the expense of readability). Numerous  examples  of
  1107.       this type of programming may by found in  the  source  code  for  the
  1108.       MICRO-C compiler.
  1109.    Intro to MICRO-C                                                 Page: 22
  1110.  
  1111.  
  1112.       4.1 Unary operators
  1113.    
  1114.             Unary (single operand)  operators  are  those  operators  which
  1115.          perform a computation on only a single value. In most  cases,  the
  1116.          operator must be placed immediatly BEFORE the value to be operated
  1117.          on.
  1118.    
  1119.          4.1.1 Negate: -
  1120.    
  1121.                The NEGATE operator causes the value  to  its  right  to  be
  1122.             changed in sign. Thus, a positive value will be converted to  a
  1123.             negative value (of the same magnitude) and vice  versa.  It  is
  1124.             most often used to enter negative numbers, but it is  perfectly
  1125.             legal to apply this operator to a variable or expression.
  1126.    
  1127.            eg:     a = -5;         /* a = negative 5 */
  1128.                    b = 10;         /* b = positive 10 */
  1129.                    c = -b;         /* c = -10 */
  1130.                    d = -(b+5);     /* d = -15 */
  1131.                    e = -b+5;       /* e = -5  *
  1132.                    f = -a;         /* f = 5   */
  1133.    
  1134.          4.1.2 Bitwise Complement: ~
  1135.    
  1136.                The BITWISE COMPLEMENT operator reverses the value (0 or  1)
  1137.             of each individual BIT in the value to its right. This is  very
  1138.             useful when used with the other BITWISE operators (AND, OR  and
  1139.             XOR), to perform test on combinations of bits in a byte  (char)
  1140.             or word (int).
  1141.    
  1142.            eg:     a = 5;          /* a = 00000101 */
  1143.                    b = ~a;         /* b = 11111010 */
  1144.    
  1145.          4.1.3 Logical Complement: !
  1146.    
  1147.                The LOGICAL COMPLEMENT operator reverse the "logical  sense"
  1148.             (TRUE or FALSE) of the value to its right. In 'C'  a  value  is
  1149.             considered to be logically TRUE if it contains any value  other
  1150.             than zero. A value of zero is considered to be logically FALSE.
  1151.             The logical complement gives a value of  zero  (FALSE)  if  the
  1152.             original value was non-zero, and a value of one (TRUE)  if  the
  1153.             original value was zero. You will  see  later  that  there  are
  1154.             CONDITIONAL statements in 'C', which perform certain operations
  1155.             only if values are TRUE. This operator provides a simple method
  1156.             of reversing those conditions to occur when the value is FALSE.
  1157.    
  1158.            eg:     if(a) b = 10;   /* Set b to 10 if a is TRUE */
  1159.                    if(!a) b = 10;  /* Set b to 10 if a is FALSE */
  1160.    Intro to MICRO-C                                                 Page: 23
  1161.  
  1162.  
  1163.          4.1.4 Increment: ++
  1164.    
  1165.                The INCREMENT operator must be used on a value that  can  be
  1166.             ASSIGNED (such as a variable or array element). It  causes  the
  1167.             value to be INCREASED by one (except for a  special  case  with
  1168.             POINTERS which are advanced by the size of the  type  to  which
  1169.             they point).
  1170.    
  1171.                Unlike most other unary operators,  the  increment  operator
  1172.             may be placed either BEFORE or AFTER  the  value,  and  behaves
  1173.             slightly differently  depending  on  its  position.  If  placed
  1174.             BEFORE the value, the variable  is  incremented,  and  the  new
  1175.             value is passed on as the result. If placed  AFTER  the  value,
  1176.             the original value is passed on as the result, and the variable
  1177.             is then incremented.
  1178.    
  1179.            eg:     a = b = 10;     /* Set a & b to 10 */
  1180.                    c = ++a;        /* c = 11 (a = 11) */
  1181.                    d = b++;        /* d = 10 (b = 11) */
  1182.    
  1183.          4.1.5 Decrement: --
  1184.    
  1185.                The  DECREMENT  operator  behaves  exactly   the   same   as
  1186.             increment,  except  that  the  value  is  REDUCED  instead   of
  1187.             increased.
  1188.    
  1189.            eg:     a = b = 10;     /* Set a & b to 10 */
  1190.                    c = --a;        /* c = 9  (a=9) */
  1191.                    d = b--;        /* d = 10 (b=9) */
  1192.    
  1193.          4.1.6 Indirection: *
  1194.    
  1195.                The INDIRECTION operator may only be applied to POINTERS, or
  1196.             expressions which result in a  POINTER  VALUE.  It  causes  the
  1197.             memory contents at the address contained in the pointer  to  be
  1198.             accessed, instead of the pointer value itself.
  1199.    
  1200.            eg:     char *ptr;      /* Declare a pointer to character */
  1201.                    ptr = 10;       /* Set pointer variable to 10 */
  1202.                    *ptr = 5;       /* Set 'char' at address 10 to 5 */
  1203.                    a = ptr;        /* a = 10 (pointer value) */
  1204.                    b = *ptr;       /* b = 5 (Indirect through address 10) */
  1205.    
  1206.          4.1.7 Address: &
  1207.    
  1208.                The ADDRESS operator may only be used on a value  which  can
  1209.             be ASSIGNED (such as a variable or array element).  It  returns
  1210.             the memory address of the value, instead of the value itself.
  1211.    
  1212.            eg:     a = 10;         /* Set variable a to 10 */
  1213.                    ptr = &a;       /* Get address of 'a' */
  1214.                    b = *ptr;       /* b = 10 (contents of 'a') */
  1215.                    *ptr = 15;      /* Store 15 at address of 'a' */
  1216.                    c = a;          /* c = 15 */
  1217.    Intro to MICRO-C                                                 Page: 24
  1218.  
  1219.  
  1220.       4.2 Binary Operators
  1221.    
  1222.             In additon to the "unary" operators presented above, 'C' has  a
  1223.          large complement of BINARY (two  operand)  operators.  The  binary
  1224.          operators take two values, presented on the left and right side of
  1225.          the operator, and combine them into some form of computed value.
  1226.    
  1227.          4.2.1 Addition: +
  1228.    
  1229.                The ADDITION operator computes the SUM of two values.
  1230.    
  1231.            eg:     a = b + 5;      /* a = sum of b and 5 */
  1232.    
  1233.          4.2.2 Subtraction: -
  1234.    
  1235.                The SUBTRACTION operator  computes  the  DIFFERENCE  of  two
  1236.             values.
  1237.    
  1238.            eg:     a = b - 5;      /* a = difference of b and 5 */
  1239.    
  1240.          4.2.3 Multiplication: *
  1241.    
  1242.                The MULTIPLICATION operator  computes  the  PRODUCT  of  two
  1243.             values.
  1244.    
  1245.            eg:     a = b * 5;      /* a = b multiplied by 5 */
  1246.    
  1247.          4.2.4 Division: /
  1248.    
  1249.                The DIVISION operator computes the QUOTIENT  resulting  from
  1250.             the division of the left value by the right value.
  1251.    
  1252.    
  1253.            eg:     a = b / 5;      /* a = b divided by 5 */
  1254.    
  1255.          4.2.5 Modulus: %
  1256.    
  1257.                The MODULUS operator computes the REMAINDER  resulting  from
  1258.             the division of the left value by the right value.
  1259.    
  1260.            eg:     a = b % 5;      /* a = remainer of b divided by 5 */
  1261.    
  1262.          4.2.6 Bitwise And: &
  1263.    
  1264.                The BITWISE AND operator performs an AND  function  on  each
  1265.             pair of bits between the values. Bit positions which have a one
  1266.             (1) bit in BOTH values will receive a one in  the  result.  All
  1267.             other bit positions will receive zero (0).
  1268.    
  1269.            eg      a = 5;          /* a = 00000101 */
  1270.                    b = 6;          /* b = 00000110 */
  1271.                    c = a & b;      /* c = 00000100 (4) */
  1272.    Intro to MICRO-C                                                 Page: 25
  1273.  
  1274.  
  1275.          4.2.7 Bitwise Or: |
  1276.    
  1277.                The BITWISE OR operator performs an OR function on each pair
  1278.             of bits between the values. Bit positions which have a one  (1)
  1279.             in EITHER value will receive a one in the result. All other bit
  1280.             positions will receive zero (0).
  1281.    
  1282.            eg      a = 5;          /* a = 00000101 */
  1283.                    b = 6;          /* b = 00000110 */
  1284.                    c = a | b;      /* c = 00000111 (7) */
  1285.    
  1286.          4.2.8 Bitwise Exclusive Or: ^
  1287.    
  1288.                The BITWISE EXCLUSIVE OR operator performs an  EXCLUSIVE  OR
  1289.             function on each pair of bits between the values. Bit positions
  1290.             which have a one (1) in EITHER value, but NOT  IN  BOTH  values
  1291.             will receive a one in the result. All other bit positions  will
  1292.             receive zero (0).
  1293.    
  1294.            eg      a = 5;          /* a = 00000101 */
  1295.                    b = 6;          /* b = 00000110 */
  1296.                    c = a ^ b;      /* c = 00000011 (3) */
  1297.    
  1298.          4.2.9 Logical And: &&
  1299.    
  1300.                The LOGICAL AND operator returns  TRUE  (non-zero)  only  if
  1301.             BOTH values are TRUE. If either value is FALSE, FALSE (zero) is
  1302.             returned.
  1303.    
  1304.                MICRO-C accomplishes this by evaluating the left value,  and
  1305.             returning zero (FALSE) if it is equal to  zero,  otherwise  the
  1306.             right value is evaluated and returned. Some 'C' compilers force
  1307.             the returned value to be either zero (0) or one (1).
  1308.    
  1309.            eg:     if(a && b)
  1310.                        printf("Both 'a' AND 'b' are TRUE");
  1311.    
  1312.          4.2.10 Logical Or: ||
  1313.    
  1314.                The LOGICAL OR operator returns TRUE  (non-zero)  if  EITHER
  1315.             value is true, if  both  values  are  FALSE,  FALSE  (zero)  is
  1316.             returned.
  1317.    
  1318.                MICRO-C accomplishes this by evaluating the left value,  and
  1319.             returning its value if it is not  zero  (TRUE),  otherwise  the
  1320.             right value is evaluated and returned. Some 'C' compilers force
  1321.             the returned value to be either zero (0) or one (1).
  1322.    
  1323.            eg:     if(a || b)
  1324.                        printf("Either 'a' OR 'b' is TRUE");
  1325.    Intro to MICRO-C                                                 Page: 26
  1326.  
  1327.  
  1328.          4.2.11 Shift Left: <<
  1329.    
  1330.                The SHIFT LEFT operator returns a value which  is  equal  to
  1331.             the left value shifted left by a number of bits  equal  to  the
  1332.             right value.
  1333.    
  1334.            eg:     a = 10;         /* a = 00001010 */
  1335.                    b = a << 3;     /* b = 01010000 (80) */
  1336.    
  1337.          4.2.12 Shift Right: >>
  1338.    
  1339.                The SHIFT RIGHT operator returns a value which is  equal  to
  1340.             the left value shifted right by a number of bits equal  to  the
  1341.             right value.
  1342.    
  1343.            eg:     a = 80;         /* a = 01010000 */
  1344.                    b = a >> 3;     /* b = 00001010 (10) */
  1345.    
  1346.          4.2.13 Equals: ==
  1347.    
  1348.                The EQUALS operator performs  a  test  of  the  values,  and
  1349.             returns a one (1) of they are identical. If they do not  match,
  1350.             a zero (0). is returned. NOTE a common  difficulty  encountered
  1351.             when learning 'C' is to confuse the EQUALS (==) and  ASSIGNMENT
  1352.             (=) operators.
  1353.    
  1354.            eg:     if(a == 10)
  1355.                        printf("a is equal to 10");
  1356.    
  1357.          4.2.14 Not Equals: !=
  1358.    
  1359.                The NOT EQUALS operator perform a test of  the  two  values,
  1360.             and returns a one (1) if they are NOT identical. If the  values
  1361.             match, a zero (0) is returned.
  1362.    
  1363.            eg:     if(a != 10)
  1364.                        printf("a is not equal to 10");
  1365.    Intro to MICRO-C                                                 Page: 27
  1366.  
  1367.  
  1368.          4.2.15 Greater Than: >
  1369.    
  1370.                The GREATER THAN operator performs a test of the two values,
  1371.             and returns a one (1) is the left  value  is  higher  than  the
  1372.             right value. If the left value is equal to  or  less  than  the
  1373.             right value, zero (0) is returned.
  1374.    
  1375.            eg:     if(a > 10)
  1376.                        printf("a is bigger than 10");
  1377.    
  1378.          4.2.16 Less Than: <
  1379.    
  1380.                The LESS THAN operator performs a test of  the  two  values,
  1381.             and returns a one (1) is the left value is lower than the right
  1382.             value. If the left value is equal to or greater than the  right
  1383.             value, zero (0) is returned.
  1384.    
  1385.            eg:     if(a < 10)
  1386.                        printf("a is smaller than 10");
  1387.    
  1388.          4.2.17 Greater Than or Equals: >=
  1389.    
  1390.                The GREATER THAN OR EQUALS operator performs a test  of  the
  1391.             two values, and returns a one (1) is the left value  is  higher
  1392.             than OR equal to the right value. If the  left  value  is  less
  1393.             than the right value, zero (0) is returned.
  1394.    
  1395.            eg:     if(a >= 10)
  1396.                        printf("a is bigger than or equal to 10");
  1397.    
  1398.          4.2.18 Less Than or Equals: <=
  1399.    
  1400.                The LESS THAN OR EQUALS operator performs a test of the  two
  1401.             values, and returns a one (1) is the left value is  lower  than
  1402.             OR equal to the right value. If the left value is greater  than
  1403.             the right value, zero (0) is returned.
  1404.    
  1405.            eg:     if(a <= 10)
  1406.                        printf("a is smaller than or equal to 10");
  1407.    Intro to MICRO-C                                                 Page: 28
  1408.  
  1409.  
  1410.          4.2.19 Assignment: =
  1411.    
  1412.                The ASSIGNMENT operator takes the value to  the  right,  and
  1413.             STORES it in the left value. The left value must be ASSIGNABLE.
  1414.    
  1415.            eg:     a = 10;     /* Store 10 in variable a */
  1416.    
  1417.          4.2.20 Self Assignment Operators
  1418.    
  1419.                'C' provides special operators which implement  a  shorthand
  1420.             method of performing an operation on two values when the result
  1421.             is stored back into the left value. These operators are  called
  1422.             SELF ASSIGNMENT operators.
  1423.    
  1424.                       Shorthand:          Equivalent to:
  1425.                    --------------------------------------
  1426.                        a += 1;             a = a + 1;
  1427.                        b -= 2;             b = b - 2;
  1428.                        c *= 3;             c = c * 3;
  1429.                        d /= 4;             d = d / 4;
  1430.                        e %= 5;             e = e % 5;
  1431.                        f &= 6;             f = f & 6;
  1432.                        g |= 7;             g = g | 7;
  1433.                        h ^= 8;             h = h ^ 8;
  1434.                        i <<= 9;            i = i << 9;
  1435.                        j >>= 10;           j = j >> 10;
  1436.    
  1437.                With most compilers, the self assignment  operators  do  not
  1438.             produce any better  code  when  using  simple  variables.  They
  1439.             simply allow you to state what you want done in  a  more  clear
  1440.             and concise manner.
  1441.    
  1442.                With MICRO-C, and most non-optimizing compilers, there is an
  1443.             advantage  to  using  the  self   assignment   operators   when
  1444.             referencing a CALCULATED ADDRESS (Such  as  when  accessing  an
  1445.             indexed array).
  1446.    
  1447.                                 array[a] += b;
  1448.    
  1449.                          Is often more efficent than:
  1450.    
  1451.                            array[a] = array[a] + b;
  1452.    Intro to MICRO-C                                                 Page: 29
  1453.  
  1454.  
  1455.       4.3 Other Operators
  1456.    
  1457.             There are a few 'C' operators which do not fall into one of the
  1458.          above clearly defined classes. Those operators are presented here:
  1459.    
  1460.          4.3.1 Statement terminator: ;
  1461.    
  1462.                We have already seen the ';' STATEMENT TERMINATOR,  this  is
  1463.             just a reminder of how important it is. Leaving out the ';'  at
  1464.             the end of a statement is a good way to convince  the  compiler
  1465.             to produce lots of error messages.
  1466.    
  1467.          4.3.2 Comma Operator: ,
  1468.    
  1469.                The function performed by the COMMA operator ',' depends  on
  1470.             where it occurs in the 'C' source file.
  1471.    
  1472.                When used within the  arguments  to  a  function  call,  its
  1473.             function is to separate each argument that is passed:
  1474.    
  1475.            eg:     function(a, b, c);
  1476.    
  1477.                When used in a DECLARATION statement,  its  function  is  to
  1478.             separate each variable name to be defined:
  1479.    
  1480.                eg: int a, b, c;
  1481.    
  1482.                When used in a global variable initialization, its  function
  1483.             is to separate the initial elements:
  1484.    
  1485.            eg:     int array[] = { 1, 2, 3 };
  1486.    
  1487.                When used in  any  expression  other  than  those  mentioned
  1488.             above, a comma allows several expressions to be used in a place
  1489.             where only one expression is expected. The  value  returned  in
  1490.             that of the RIGHTMOST expression:
  1491.    
  1492.            eg:     return a=4, 10;     /* Set a = 4, and return 10 */
  1493.    Intro to MICRO-C                                                 Page: 30
  1494.  
  1495.  
  1496.          4.3.3 Conditional Operator: ?
  1497.    
  1498.                The CONDITIONAL operator  allows  you  to  create  a  single
  1499.             expression which evaluates one of two SUB-EXPRESSIONS depending
  1500.             on a logical condition. It is coded in the 'C'  source  program
  1501.             in the form:
  1502.    
  1503.              <condition> ? <TRUE expression> : <FALSE expression>
  1504.    
  1505.                Consider, the standard  library  function  "toupper",  which
  1506.             converts any  lower  case  character  to  upper  case.  If  the
  1507.             original character was lower case, no conversion is  made,  and
  1508.             the character is returned unchanged.
  1509.    
  1510.                Knowing that in ASCII, lower case characters  have  a  value
  1511.             equal to the equivalent upper case character  +  64,  we  could
  1512.             code the following function:
  1513.    
  1514.                /* Function to convert lower case to upper case */
  1515.                char toupper(chr)
  1516.                    char chr;
  1517.                {
  1518.                    if((chr >= 'a') && (chr <= 'z'))    /* lower case ? */
  1519.                        return chr - 64;                /* Convert */
  1520.                    else
  1521.                        return chr;                     /* Leave alone */
  1522.                }
  1523.    
  1524.                The same function coded using a conditional expression is:
  1525.    
  1526.                /* Function to convert lower case to upper case */
  1527.                char toupper(chr)
  1528.                    char chr;
  1529.                {
  1530.                    return (chr >= 'a') && (chr <= 'z') ? chr - 64 : chr;
  1531.                }
  1532.    
  1533.                Although the difference between the above two functions  may
  1534.             seem  trivial,  remember  that  you  can  use  ANY   expression
  1535.             (including a CONDITIONAL expression) anywhere  that  you  could
  1536.             place a simple value. Once you get the hang of that,  you  will
  1537.             find that conditional expressions are a very  powerful  feature
  1538.             of the 'C' language.
  1539.    Intro to MICRO-C                                                 Page: 31
  1540.  
  1541.  
  1542.          4.3.4 Round Brackets: ( )
  1543.    
  1544.                The ROUND BRACKETS are used by 'C' to perform two functions.
  1545.             First, as already mentioned, they identify function calls,  and
  1546.             hold any arguments which are being passed:
  1547.    
  1548.            eg:     function1();
  1549.                    function2(a);
  1550.                    function3(a, b);
  1551.    
  1552.                The round brackets are also used to set up a SUB EXPRESSION,
  1553.             which can be used within another expression as a simple value:
  1554.    
  1555.            For example:
  1556.    
  1557.                    b = a + 5;
  1558.                    c = b / 2;
  1559.    
  1560.            Can be replaced by:
  1561.    
  1562.                    c = (a + 5) / 2;
  1563.    
  1564.            Or, if you want 'b' assigned:
  1565.    
  1566.                    c = (b = a + 5) / 2;
  1567.    
  1568.          4.3.5 Square Brackets: [ ]
  1569.    
  1570.                The SQUARE BRACKETS are used to perform indexing.  Variables
  1571.             which  have  been  declared   as   ARRAYS   may   be   indexed.
  1572.             MULTIDIMENSIONAL arrays may be  indexed  by  using  a  pair  of
  1573.             square brackets for each dimension:
  1574.    
  1575.            eg:     int array1[4], array2[2][2];
  1576.    
  1577.                    array1[0] = 10;
  1578.                    a = array1[1];
  1579.                    b = array2[1][0];
  1580.    
  1581.                If a multidimensional array is  indexed  with  a  number  of
  1582.             square  bracket  pairs  which  is  less  that  the  number   of
  1583.             dimsnsions of the array, the value returned is a POINTER  VALUE
  1584.             to the beginning address of the next dimension. A  pointer  may
  1585.             be indexed as it they were single dimension array,  the  memory
  1586.             offsets added to the pointer will be calculated  based  on  the
  1587.             size of the data type to which it has been declared to point:
  1588.    
  1589.            eg:     int array[3][3], *ptr;
  1590.    
  1591.                    array[2][1] = 10;
  1592.                    ptr = array[2];
  1593.                    a = ptr[1];         /* a = 10 */
  1594.    Intro to MICRO-C                                                 Page: 32
  1595.  
  1596.  
  1597.    5. CONTROL STATEMENTS
  1598.    
  1599.          There are a number of statements in 'C', which  serve  to  control
  1600.       the flow of program execution.
  1601.    
  1602.       5.1 The IF statement
  1603.    
  1604.             The IF statement controls the execution of one other statement,
  1605.          based of  the  logical  value  (TRUE  or  FALSE)  of  a  CONDITION
  1606.          EXPRESSION:
  1607.    
  1608.            if(condition)
  1609.                statement;
  1610.    
  1611.             The "statement" in the above example would only be executed  if
  1612.          "condition" evaluated to a logically TRUE (non zero) value.
  1613.    
  1614.             An optional "else" clause may be added to the IF statement.  In
  1615.          this example, "statement-1" is executed if  "condition"  evaluates
  1616.          to TRUE, and "statement-2" is executed if "condition" evaluates to
  1617.          FALSE.
  1618.    
  1619.            if(condition)
  1620.                statement-1;
  1621.            else
  1622.                statement-2;
  1623.    
  1624.       5.2 The WHILE Loop
  1625.    
  1626.             The WHILE  statement  is  similar  to  the  first  form  of  IF
  1627.          statement (without  an  else),  except  that  the  "statement"  is
  1628.          repeated until the condition becomes  FALSE.  If  the  "statement"
  1629.          does not effect the condition, the statement will be executed over
  1630.          and over forever (ie: infinite loop).
  1631.    
  1632.            while(condition)
  1633.                statement;
  1634.    
  1635.             Try entering, compiling and executing the following program:
  1636.    
  1637.            #include stdio.h
  1638.            /* Our old familiar "count to 10" program, with a few
  1639.               improvements to let us see the numbers */
  1640.            main()
  1641.            {
  1642.                int a;
  1643.    
  1644.                a = 0;
  1645.                while(a < 10)
  1646.                    printf("A=%d\n", a++);
  1647.            }
  1648.    Intro to MICRO-C                                                 Page: 33
  1649.  
  1650.  
  1651.             Note the '\n' at the end of the prompt in the call to "printf".
  1652.          'C' operates on a concept called STREAM I/O, which means that  all
  1653.          input and  output  is  considered  to  occur  in  a  never  ending
  1654.          "stream", like a stream of water. There  are  no  "lines"  in  the
  1655.          stream unless we cause them. The '\n' sequence at the end  of  the
  1656.          prompt is a NEWLINE character, which tells the compiler to  insert
  1657.          the necessary code into the string to cause the output to go to  a
  1658.          NEW LINE on a terminal or printer when the  string  is  displayed.
  1659.          Try removing the '\n' from the prompt and see what happens.
  1660.    
  1661.       5.3 The DO/WHILE Loop
  1662.    
  1663.             The DO/WHILE statement  is  similar  to  the  WHILE  statement,
  1664.          except that  the  condition  is  tested  AFTER  the  statement  is
  1665.          executed, not BEFORE. Note  that  when  using  DO/WHILE,  you  are
  1666.          guarenteed that the statement will always  be  executed  at  least
  1667.          ONCE.
  1668.    
  1669.            do
  1670.                statement;
  1671.            while(conditon);
  1672.    
  1673.             Here is another example of our "count" program, which uses  our
  1674.          own function to output the number in decimal:
  1675.    
  1676.            #include stdio.h
  1677.    
  1678.            /* Main "count" program */
  1679.            main()
  1680.            {
  1681.                int a;
  1682.    
  1683.                a = 0;
  1684.                do
  1685.                    outnum(a);
  1686.                while(++a < 10);
  1687.            }
  1688.    
  1689.            /* Function to output a number in decimal */
  1690.            outnum(value)
  1691.                unsigned value;
  1692.            {
  1693.                char stack[6];      /* Small stack to hold digits */
  1694.                unsigned sp;        /* Our own stack pointer */
  1695.    
  1696.            /* calculate each digit of the number (in reverse order) */
  1697.                sp = 0;
  1698.                do
  1699.                    stack[sp++] = (value % 10) + '0';
  1700.                while(value /= 10);
  1701.            /* Display the stack of calculated digits */
  1702.                while(sp)
  1703.                    putc(stack[--sp], stdout);
  1704.                putc('\n', stdout);     /* move to new line */
  1705.            }
  1706.    Intro to MICRO-C                                                 Page: 34
  1707.  
  1708.  
  1709.             The "putc" function  is  another  function  from  the  STANDARD
  1710.          LIBRARY. The name "stdout" is defined in the "stdio.h"  file,  and
  1711.          tells "putc" that the character should  be  written  to  "standard
  1712.          output" (The PC console).
  1713.    
  1714.             The DO/WHILE loop in the "outnum" function demonstrates a  case
  1715.          where a simple  WHILE  would  not  suffice.  Try  to  re-code  the
  1716.          function using only WHILE loops. You might try:
  1717.    
  1718.            sp = 0;
  1719.            while(value)
  1720.                stack[sp++] = (value % 10) + '0', value /= 10;
  1721.    
  1722.          This appears to work, however, try executing "outnum(0)". The loop
  1723.          is never executed,  "sp"  is  never  incremented  from  zero,  and
  1724.          NOTHING is output. Not even a single '0'.
  1725.    
  1726.       5.4 The FOR Loop
  1727.    
  1728.             Notice that in the example above, we have to  initialize  "sp",
  1729.          test "value", and perform an operation on value at the end of  the
  1730.          loop. 'C' provides a special loop construct, just for  doing  such
  1731.          operations. It is called a FOR loop:
  1732.    
  1733.            for(initialization; condition; operation)
  1734.                statement;
  1735.    
  1736.             Using the FOR loop, we can rewrite the above example as:
  1737.    
  1738.            for(sp = 0; value; value /= 10)
  1739.                stack[sp++] = (value % 10) + '0';
  1740.    
  1741.             Actually, the FOR loop is more often used to  implement  simple
  1742.          loops which execute a predetermined number of times:
  1743.    
  1744.            /* A count loop, which executes 10 times */
  1745.            for(a=0; a < 10; ++a)
  1746.                printf("A=%d\n", a);
  1747.    
  1748.             Sometimes, it is possible to do all the computations  that  are
  1749.          required in  the  "initialization",  "condition"  and  "operation"
  1750.          expressions to the FOR loop. In  this  case,  you  could  use  the
  1751.          SEMICOLON ';' as the entire "statement" to tell FOR that  and  you
  1752.          don't want it to perform any other operations:
  1753.    
  1754.            for(a=0; a < 10; printf("A=%d\n", a++))
  1755.                ;       /* This is a NULL statement */
  1756.    Intro to MICRO-C                                                 Page: 35
  1757.  
  1758.  
  1759.             This semicolon by itself is called a NULL statement, and can be
  1760.          used anywhere that any other statement would be used.
  1761.    
  1762.            a = 0;
  1763.            while(a++ < 100)
  1764.                ;
  1765.    
  1766.            if(a == b)
  1767.                ;
  1768.            else
  1769.                printf("a is not equal to b");
  1770.    
  1771.             Note that the expressions in a FOR statement end with ';'. This
  1772.          means that they are also optional, and could be replaced  by  NULL
  1773.          statements.
  1774.    
  1775.            for(; a < 10; ++a) ;    /* No initialization */
  1776.            for(a = 0;; ++a) ;      /* No condition (infinite loop) */
  1777.            for(a = 0; ++a < 10;) ; /* No operation at end of loop */
  1778.            for(;;) ;               /* Standard way to do infinite loop */
  1779.    
  1780.       5.5 Compound Statements
  1781.    
  1782.             This is all well and good you say, but IF, WHILE, DO/WHILE  and
  1783.          FOR seem quite limited in that the "condition" or  "loop"  applies
  1784.          only to a single statement. What if I want to perform more complex
  1785.          calculations in my loop?
  1786.    
  1787.             Another very powerful feature of the 'C' language, is that  any
  1788.          number of ordinary statements may be placed together  in  a  group
  1789.          and treated as a single large statement. All you have to do is  to
  1790.          enclose them in CURLY BRACKETS '{ }'. For example:
  1791.    
  1792.            if(a == 10) {       /* '{' begins compound statement */
  1793.                printf("A was equal to 10... ");
  1794.                a = 99;
  1795.                printf("But its not anymore"); }    /* '}' ends */
  1796.            else
  1797.                printf("A was never equal to 10");
  1798.    
  1799.             You have already seen an example of compound statements, in the
  1800.          curly brackets which surround the body of functions.  Technically,
  1801.          each function consists of only one statement, but thanks  to  'C's
  1802.          compounding capability, you can actually use as many statements as
  1803.          you wish.
  1804.    Intro to MICRO-C                                                 Page: 36
  1805.  
  1806.  
  1807.       5.6 BREAK and CONTINUE
  1808.    
  1809.             Two more  'C'  statements  are  available  which  are  designed
  1810.          specially for extending the capabilities of loops.
  1811.    
  1812.             The BREAK statement causes the program to  skip  any  remaining
  1813.          statements in the loop, and to break out of  the  loop.  Execution
  1814.          will proceed with the first statement which follows the loop, just
  1815.          as if the loop had terminated in its normal fashion:
  1816.    
  1817.            for(a=0; a < 10; ++a) {
  1818.                if(a == 5)
  1819.                    break;
  1820.                printf("A=%d\n", a); }
  1821.    
  1822.             The above loop will never  reach  its  terminal  count  of  10,
  1823.          because the "break" statement will be executed  when  'a'  reaches
  1824.          five. Thus, the BREAK statement allows you to sprinkle  additional
  1825.          exit conditions throughout the body of the loop.
  1826.    
  1827.             The CONTINUE statement causes the loop to  skip  any  remaining
  1828.          statements in the loop, but to continue  looping.  Execution  will
  1829.          proceed as  if  all  the  statements  in  the  loop  had  executed
  1830.          normally:
  1831.    
  1832.            for(a=0; a < 10; ++a) {
  1833.                if(a != 5)
  1834.                    continue;
  1835.                printf("A=%d\n", a); }
  1836.    
  1837.             The above example will execute all 10 interations of the  loop,
  1838.          but the "printf" statement will only be executed for the  loop  in
  1839.          which 'a' is equal to 5.
  1840.    
  1841.       5.7 The SWITCH Statement
  1842.    
  1843.             Sometimes, you have a large number of conditions, which are  to
  1844.          be executed depending on the value of a certain variable. One  way
  1845.          that you could do this is with a series of "IF" statements,  using
  1846.          a popular "else if" construct:
  1847.    
  1848.            if(a == 1)
  1849.                statement-1;        /* Executed if a == 1 */
  1850.            else if(a == 2)
  1851.                statement-2;        /* Executed if a == 2 */
  1852.            else if(a == 3)
  1853.                statement-3;        /* Executed if a == 3 */
  1854.            else if(a == 4) {       /* Note compound statement */
  1855.                statement-4;        /* Executed if a == 4 */
  1856.                statement-5; }      /* Executed if a == 4 */
  1857.            else
  1858.                statement-6;        /* Executed if a == anything else */
  1859.    Intro to MICRO-C                                                 Page: 37
  1860.  
  1861.  
  1862.             'C' has  a  built  in  statement  to  implement  this  kind  of
  1863.          structure. It is more readable, and generates more  efficent  code
  1864.          than such a series of "IF"  statements.  It  is  called  a  SWITCH
  1865.          statement:
  1866.    
  1867.            switch(a) {
  1868.                case 1 :
  1869.                    statement-1;        /* Executed if a == 1 */
  1870.                    break;
  1871.                case 2 ;
  1872.                    statement-2;        /* Executed if a == 2 */
  1873.                    break;
  1874.                case 3 :
  1875.                    statement-3;        /* Executed if a == 3 */
  1876.                    break;
  1877.                case 4 :
  1878.                    statement-4;        /* Executed if a == 4 */
  1879.                    statement-5;        /* Executed if a == 4 */
  1880.                    break;
  1881.                default:
  1882.                    statement-6; }      /* Executed of a == anything else */
  1883.    
  1884.             The "BREAK" statement at the  end  of  every  CASE  causes  the
  1885.          program to proceed to the statement immediately following the  end
  1886.          of the entire switch  construct.  If  it  were  not  present,  the
  1887.          statements in  a  case  would  "fall  through",  and  execute  the
  1888.          statements in the following case as well. Since the case values do
  1889.          not have to be presented in any particular  order,  this  behavior
  1890.          can often be used to your advantage by careful placing of the case
  1891.          statements relative to each other. Note also that the code in  the
  1892.          last case ("Default") does not need a "break" since it is  already
  1893.          at the end of the switch construct.
  1894.    
  1895.       5.8 Labels and GOTO
  1896.    
  1897.             If none of the above constructs does exactly what you  need  to
  1898.          structure a particular program. 'C' also  has  available  the  old
  1899.          familiar GOTO command. Although the use of "GOTO" is often frowned
  1900.          upon, it can save you much programming effort in  some  cases.  In
  1901.          order to use goto, you must have a LABEL.  Any  statement  may  be
  1902.          labeled by preceeding it with a name, followed immediatly by  ':'.
  1903.          For example:
  1904.    
  1905.            #include stdio.h
  1906.            /* Our "count to 10" program using goto looping */
  1907.            main()
  1908.            {
  1909.                int a;
  1910.    
  1911.                a = 0;
  1912.            count: printf("A=%d\n", a);     /* Labeled "count" */
  1913.                if(++a < 10)
  1914.                    goto count;
  1915.            }
  1916.    Intro to MICRO-C                                                 Page: 38
  1917.  
  1918.  
  1919.    6. RECURSION
  1920.    
  1921.          RECURSION is the ability of a function to call itself,  and  is  a
  1922.       powerful capability of the 'C' language.
  1923.    
  1924.          In a previous section, I explained how memory is allocated on  the
  1925.       stack to a function  when  it  begins  execution.  This  allows  each
  1926.       function to have its own local variables. It also  means  that  if  a
  1927.       function calls itself (by referencing its own name in  an  expression
  1928.       contained within it), the function will begin executing with its  own
  1929.       local memory, which is distinct from the local memory of the  calling
  1930.       function (which  is  itself!).  This  means  that  when  the  "lower"
  1931.       instance of the function terminates, it will not  have  affected  the
  1932.       memory or execution state of the "higher" version of the function.
  1933.    
  1934.          The classic example of a recursive  algorithm  is  the  FACTORIAL,
  1935.       which may be defined as: factorial(n) is equal  the  product  of  all
  1936.       numbers from one to n.
  1937.    
  1938.          Thus:
  1939.                    factorial(1) == 1       /* 1         */
  1940.                    factorial(2) == 2       /* 1*2       */
  1941.                    factorial(3) == 6       /* 1*2*3     */
  1942.                    factorial(4) == 24      /* 1*2*3*4   */
  1943.                    factorial(5) == 120     /* 1*2*3*4*5 */
  1944.    
  1945.          Using this algorithm, we can define an  ITERATIVE  (non-recursive)
  1946.       function to calculate the factorial of a passed value:
  1947.    
  1948.                /*
  1949.                 * ITERATIVE factorial function
  1950.                 */
  1951.                unsigned factorial(value)
  1952.                    unsigned value;
  1953.                {
  1954.                    unsigned result;
  1955.    
  1956.                    result = 1;             /* Begin with one */
  1957.                    while(value > 1)        /* For each value */
  1958.                        result *= value--;  /* Include in product & reduce */
  1959.    
  1960.                    return result;          /* Send back result */
  1961.                }
  1962.    
  1963.          You can see that in this above example, the function simply  loops
  1964.       the required number of times to perform  the  appropriate  number  of
  1965.       multiply operations to calculate the factorial. (The factorial  of  0
  1966.       is defined as 1, NOT 0, so the above function will return the correct
  1967.       result in this case).
  1968.    Intro to MICRO-C                                                 Page: 39
  1969.  
  1970.  
  1971.          Another way to define factorial is: factorial(n) = the product  of
  1972.       n and factorial(n-1). (Remember that the factorial of zero is defined
  1973.       as 1).
  1974.    
  1975.          Thus:
  1976.                    factorial(1) == 1       /* 1*1  */
  1977.                    factorial(2) == 2       /* 2*1  */
  1978.                    factorial(3) == 6       /* 3*2  */
  1979.                    factorial(4) == 24      /* 4*6  */
  1980.                    factorial(5) == 120     /* 5*24 */
  1981.    
  1982.          Using this algorithim, we  can  define  a  RECURSIVE  function  to
  1983.       calculate the factorial of a passed value:
  1984.    
  1985.                /*
  1986.                 * RECURSIVE factorial function
  1987.                 */
  1988.                unsigned factorial(value)
  1989.                    unsigned value;
  1990.                {
  1991.                    if(value == 0)  /* Factorial 0 is 1 */
  1992.                        return 1;
  1993.    
  1994.                    return value * factorial(value - 1);
  1995.                }
  1996.    
  1997.          In this example, you can see that the function will  call  itself,
  1998.       each  time  passing  a  reduced  value  until  a  value  of  zero  is
  1999.       encountered. When the zero value is passed, "factorial"  returns  the
  2000.       pre-defined result of one, and  all  other  called  versions  of  the
  2001.       function will perform a  single  multiplication,  and  pass  the  new
  2002.       result on. The value returned by the "highest" version of "factorial"
  2003.       will be the factorial of the originally passed value.
  2004.    
  2005.          This is the "classic" example of recursion, and it is a poor  one.
  2006.       Although it demonstrates the concept,  it  does  not  show  a  useful
  2007.       application. In fact, the recursive factorial function  will  execute
  2008.       slower and require much more memory  than  the  interative  function.
  2009.       (Remember each "version" of the function gets its own local memory).
  2010.    
  2011.          The MICRO-C compiler  itself  relies  heavily  on  recursion,  and
  2012.       provides much better examples of this programming technique since  it
  2013.       is  used  to  accomplish  feats  which  are  not  possible  using   a
  2014.       non-recursive algorithm.
  2015.    
  2016.          One such use of recursion in the compiler is  to  accomplish  'C's
  2017.       COMPOUND STATEMENT capability. Recall that multiple statements in 'C'
  2018.       may be  grouped  together  and  treated  as  a  single  statement  by
  2019.       enclosing them in CURLY BRACKETS  '{}'.  Any  statement  within  this
  2020.       "group" may also be a  compound  statement,  and  this  "nesting"  of
  2021.       compound statement blocks may continue to ANY LEVEL.
  2022.    Intro to MICRO-C                                                 Page: 40
  2023.  
  2024.  
  2025.          The compiler contains a  function  called  "statement",  which  is
  2026.       passed the first token from  a  'C'  statement,  and  processes  that
  2027.       statement.  This  function  contains  a  "switch"   statement   which
  2028.       processes the token, and decides the action to be performed for  that
  2029.       statement.  Note:  "tokens"  are  numeric  representations   of   the
  2030.       individual entities which may occur  in  the  source  file  (such  as
  2031.       keywords, symbol names, operators etc.).
  2032.    
  2033.          The "statement" function contains a  fragment  of  code  which  is
  2034.       similar to this:
  2035.    
  2036.                /*
  2037.                 * Evaluate a language statement
  2038.                 */
  2039.                statement(token)
  2040.                    unsigned token;
  2041.                {
  2042.                    /* ... Not shown ... */
  2043.                    switch(token) {     /* act upon the token */
  2044.                        /* ... Not shown ... */
  2045.                        case OCB:       /* '{' - begin a block */
  2046.                            while((token = get_token()) != CCB)
  2047.                                statement(token);
  2048.                            break;
  2049.                        /* ... Not shown ... */
  2050.                        case WHILE:
  2051.                            /* ... Not shown ... */
  2052.                            eval(CRB, 0);
  2053.                            cond_jump(FALSE, b, -1);
  2054.                            statement(get_token());
  2055.                            test_jump(a);
  2056.                            /* ... Not shown ... */
  2057.                            break;
  2058.                        /* ... Not shown ... */ }
  2059.                }
  2060.    
  2061.          In  this  function,  a  "while"  keyword  causes   the   following
  2062.       expression to be evaluated, followed by  a  conditional  jump,  after
  2063.       which  a  single  statement  is  compiled  (by  recursive   call   to
  2064.       "statement"), followed by  a  jump  back  to  the  beginning  of  the
  2065.       expression evaluation.
  2066.    
  2067.          If "statement" finds an  Opening  Curly  Bracket  (OCB),  it  will
  2068.       accept and compile more statements (recursivly) until a Closing Curly
  2069.       Bracket (CCB) is found. Therefore, if the statement compiled  in  the
  2070.       "while" loop  begins  with  OCB,  that  version  of  the  "statement"
  2071.       function will compile all subsequent statements up to CCB. When  that
  2072.       version of  "statement"  terminates,  the  original  version  of  the
  2073.       function (handling the "while") will then compile the  closing  jump.
  2074.       This has the effect that all statements between OCB and CCB ('{'  and
  2075.       '}') will be included in the body of the "while" loop.
  2076.    
  2077.          Another case where recursion is used within the MICRO-C  compiler,
  2078.       is to evaluate sub-expressions (contained  in  round  brackets  '()')
  2079.       which are inside another expression. In  this  case,  the  expression
  2080.       evaluation function calls itself (recursivly) when an  Opening  Round
  2081.       Bracket (ORB) is encountered.
  2082.    Intro to MICRO-C                                                 Page: 41
  2083.  
  2084.  
  2085.    7. COMMAND LINE ARGUMENTS
  2086.    
  2087.          When a 'C' program is invoked  by  typing  its  name  at  the  DOS
  2088.       command prompt, the remainder of the command line is broken down into
  2089.       distinct "words" (based on separating spaces or tabs), and passed  as
  2090.       standard 'C' arguments to the main function.
  2091.    
  2092.          Two values are passed to "main", the first is an integer count  of
  2093.       the number of command line arguments which were found, and the second
  2094.       is an array of pointers to character strings which  contain  each  of
  2095.       the arguments. In order that the program  may  identify  itself,  the
  2096.       first (zero'th) argument is always the name of  the  file  containing
  2097.       the programs executable image.
  2098.    
  2099.          For example, consider this program, compiled and saved in  a  file
  2100.       called "TEST.COM":
  2101.    
  2102.            #include stdio.h        /* Standard I/O definitions */
  2103.    
  2104.            /*
  2105.             * Command line arguments - DEMO program
  2106.             */
  2107.            main(argc, argv)
  2108.                int argc;       /* Count of arguments */
  2109.                char *argv[]    /* Array of pointers to char strings */
  2110.            {
  2111.                int i;          /* Temporary counter variable */
  2112.    
  2113.                for(i=0; i < argc; ++i)
  2114.                    printf("argv[%d] = '%s'\n", i, argv[i]);
  2115.            }
  2116.    
  2117.          When executed with the following command line:
  2118.    
  2119.                            TEST the quick brown fox
  2120.    
  2121.          The program will display the following output:
  2122.    
  2123.            argv[0] = 'TEST.COM'
  2124.            argv[1] = 'the'
  2125.            argv[2] = 'quick'
  2126.            argv[3] = 'brown'
  2127.            argv[4] = 'fox'
  2128.    
  2129.          NOTE1: The 'argc' value includes argv[0]  (program  name)  in  its
  2130.       argument count.
  2131.    
  2132.          NOTE2: Like any other  'C'  function,  "main"  does  not  have  to
  2133.       declare its arguments unless it is going to use them.
  2134.    Intro to MICRO-C                                                 Page: 42
  2135.  
  2136.  
  2137.    8. FILE ACCESS
  2138.    
  2139.          As mentioned before, all I/O  in  'C'  is  performed  by  STANDARD
  2140.       LIBRARY FUNCTIONS. Before any  file  access  can  be  performed,  the
  2141.       header file "stdio.h" must be included in the  source  (Via  #include
  2142.       pre-processor directive), in order to  properly  define  the  various
  2143.       functions and types which are used on your particular system.
  2144.    
  2145.          For  detailed  information  on  the  standard  library   functions
  2146.       mentioned below, see the MICRO-C technical manual.
  2147.    
  2148.       8.1 File Pointers
  2149.    
  2150.             All files in 'C' are identified by a FILE POINTER, which  is  a
  2151.          value returned by the operating system when the  file  is  OPENED.
  2152.          Since the type of value used to identify files may vary  from  one
  2153.          operating system to another, the "stdio.h" header file  defines  a
  2154.          data type called "FILE" which contains the correct definition  for
  2155.          your particular operating system. This allows the  declaration  of
  2156.          the file pointers to  be  portable  from  one  system  to  another
  2157.          without changing the program source code.
  2158.    
  2159.       8.2 File I/O Functions
  2160.    
  2161.             The standard library function "fopen" is used to open a file by
  2162.          name, and obtain the file pointer value.
  2163.    
  2164.             The functions "getc", "fread", "fgets" and "fscanf" may be used
  2165.          to read information from an open file.
  2166.    
  2167.             The functions "putc", "fwrite", "fputs" and  "fprintf"  may  be
  2168.          used to write information to an open file.
  2169.    
  2170.             The function "fclose" is used to close the file, which  informs
  2171.          the operating system that you are finished with it.
  2172.    Intro to MICRO-C                                                 Page: 43
  2173.  
  2174.  
  2175.                /*
  2176.                 * Sample program to copy a file called "input"
  2177.                 * To a file called "output". Note: To keep this
  2178.                 * example simple, no error checking is perormed.
  2179.                 */
  2180.                main()
  2181.                {
  2182.                    char buffer[1000];  /* Declare a copy buffer */
  2183.                    int nbytes;         /* Records # bytes read */
  2184.                    FILE *ifp, *ofp     /* Declare file pointers */
  2185.    
  2186.                /* Open the files */
  2187.                    ifp = fopen("input","r");   /* Open for Read access */
  2188.                    ofp = fopen("output", "w"); /* Open for Write access */
  2189.    
  2190.                /* Copy data in 1000 byte blocks */
  2191.                    do {
  2192.                        nbytes = fread(buffer, 1000, fp);   /* Read data */
  2193.                        fwrite(buffer, nbytes, fp); }       /* Write data */
  2194.                    while(nbytes == 1000);
  2195.    
  2196.                    fclose(ifp);            /* Close the input file */
  2197.                    fclose(ofp);            /* Close the output file */
  2198.                }
  2199.    
  2200.       8.3 Standard I/O
  2201.    
  2202.             Whenever a 'C' program is executed,  three  file  pointers  are
  2203.          automatically  established  which  allow  access  to  the  console
  2204.          keyboard and display:
  2205.    
  2206.            stdin   - Reads input from the console keyboard. Note that stdin
  2207.                      may be REDIRECTED (using '<filename'). For example:
  2208.                               program <input.dat
  2209.                      executes "program", and causes it to read its standard
  2210.                      input from "input.dat" instead of the keyboard.
  2211.    
  2212.            stdout  - Writes to the console display. Note that stdout may be
  2213.                      REDIRECTED (using '>filename). For example:
  2214.                              program >output.dat
  2215.                      executes "program", and causes  it to  write  standard
  2216.                      output to "output.dat" instead of the display.
  2217.    
  2218.            stderr  - Also writes to  the  console display,  but  CANNOT  BE
  2219.                      REDIRECTED, usually used to insure that error messages
  2220.                      will be displayed on the console even  if  the  output
  2221.                      has been redirected.
  2222.    
  2223.             The stdin, stdout and stderr file pointers are defined  in  the
  2224.          "stdio.h" header file, and are always available. They do not  have
  2225.          to be opened or closed.
  2226.    
  2227.             Since "stdin" and "stdout"  are  used  very  often  within  'C'
  2228.          programs, the functions "scanf" and "printf" are available.  These
  2229.          behave exactly the same as  the  general  "fscanf"  and  "fprintf"
  2230.          functions, except that they do not accept a file pointer argument,
  2231.          and always access stdin and stdout.
  2232.    Intro to MICRO-C                                                 Page: 44
  2233.  
  2234.  
  2235.    9. SAMPLE FUNCTIONS
  2236.    
  2237.          Here are some sample 'C' functions, demonstrating features of  'C'
  2238.       which we have discussed:
  2239.    
  2240.          Any function used in an example  but  not  defined  therein  is  a
  2241.       Library Function.  Refer  to  the  MICRO-C  Technical  Manual  for  a
  2242.       description.
  2243.    
  2244.       9.1 Prime Number Generator
  2245.    
  2246.            #include stdio.h        /* Standard I/O definitions */
  2247.    
  2248.            /*
  2249.             * This program tests a range of numbers, and prints out any
  2250.             * values which it finds to be prime. Each value is divided
  2251.             * by increasing values from 2 to (num/2). The "modulus" ('%')
  2252.             * operator is used, resulting in a zero result (no remainder)
  2253.             * if a factor is found. The main loop is incremented by two,
  2254.             * to skip even numbers which are never prime (except for 2
  2255.             * which is not shown by this program).
  2256.             */
  2257.            main()
  2258.            {
  2259.                int num, test, limit;
  2260.                char flag;
  2261.    
  2262.                for(num=1; num < 1000; num += 2) {      /* Test range */
  2263.                    limit = num/2;                      /* Only test to 1/2 */
  2264.                    flag = 1;                           /* Assume prime */
  2265.                    for(test = 2; test < limit; ++test) { /* Test factors */
  2266.                        if(!(num%test)) {               /* No remain: factor */
  2267.                            flag = 0;                   /* Not prime */
  2268.                            break; } }                  /* Waste no more time */ 
  2269.                    if(flag)                            /* Prime, display */
  2270.                        printf("%d\n", num); }
  2271.            }
  2272.    Intro to MICRO-C                                                 Page: 45
  2273.  
  2274.  
  2275.       9.2 A Simple Sort
  2276.    
  2277.            #include stdio.h        /* Standard I/O definitions */
  2278.    
  2279.            /*
  2280.             * This is an array of unsorted numbers
  2281.             */
  2282.            int numbers[10] = { 13, 25, 22, 7, 16, 91, 11, 41, 18, 0 };
  2283.    
  2284.            /*
  2285.             * This main program calls a function "sort" which re-arranges
  2286.             * the elements of an integer array to place them in ascending
  2287.             * order. It then prints out the resultant array using a simple
  2288.             * loop.
  2289.             */
  2290.            main()
  2291.            {
  2292.                int i;
  2293.    
  2294.                sort(numbers, 10);      /* Perform the sort */
  2295.    
  2296.                for(i=0; i < 10; ++i)   /* Display contents of array */
  2297.                    printf("[%d]=%d\n", i, numbers[i]);
  2298.            }
  2299.    
  2300.            /*
  2301.             * Function to sort an array of numbers. It is passed the
  2302.             * address of an integer array, and the size (in elements).
  2303.             *
  2304.             * Note: The declaration 'int array[]' identifies "array" as a
  2305.             * single dimension integer array of unspecified size. Since
  2306.             * arrays in 'C' are passed as a pointer value to the array
  2307.             * address, accesses to "array" will access the actual contents
  2308.             * of the passed array variable, allowing that variable to be
  2309.             * modified directly by this function.
  2310.             */
  2311.            sort(array, size)
  2312.                int array[], size;
  2313.            {
  2314.                int i, j, lowest;
  2315.    
  2316.                for(i=0; i < size; ++i) {           /* For each element */
  2317.                    lowest = i;
  2318.                    for(j=i+1; j < size; ++j)       /* Search higher elems */
  2319.                        if(array[j] < array[lowest])
  2320.                            lowest = j;             /* And remember lowest */
  2321.                    j = array[lowest];              /* Swap with original */
  2322.                    array[lowest] = array[i];
  2323.                    array[i] = j; }
  2324.            }
  2325.    Intro to MICRO-C                                                 Page: 46
  2326.  
  2327.  
  2328.       9.3 Text Display of Value
  2329.    
  2330.             This program accepts any  number  of  command  line  arguments,
  2331.          which it evaluates as unsigned numbers, and  displays  the  result
  2332.          for each argument using english text.
  2333.    
  2334.             For example, if this  program  were  saved  in  a  file  called
  2335.          "TEXTNUM.COM", and the following command is executed:
  2336.    
  2337.                TEXTNUM 1000 1100 1111 31415 9265 358
  2338.    
  2339.             The program will display the following output:
  2340.    
  2341.                One Thousand
  2342.                One Thousand, One Hundred
  2343.                One Thousand, One Hundred and Eleven
  2344.                Thirty One Thousand, Four Hundred and Fifteen
  2345.                Nine Thousand, Two Hundred and Sixty Five
  2346.                Three Hundred and Fifty Eight
  2347.    
  2348.             Here is a listing of the program:
  2349.    
  2350.            #include stdio.h
  2351.    
  2352.            /*
  2353.             * Main program which processes all of its arguments,
  2354.             * interpreting each one as a numeric value, and
  2355.             * displaying that value as english text.
  2356.             */
  2357.            main(argc, argv)
  2358.                int argc;
  2359.                char *argv[];
  2360.            {
  2361.                int i;
  2362.    
  2363.                if(argc < 2)                /* No arguments given */
  2364.                    abort("\nUse: textnum <value> ...\n");
  2365.    
  2366.                for(i=1; i < argc; ++i) {   /* Display all arguments */
  2367.                    textnum(atoi(argv[i]));
  2368.                    putc('\n', stdout); }
  2369.            }
  2370.    
  2371.            /* >>> Continued on Next Page >>> */
  2372.    Intro to MICRO-C                                                 Page: 47
  2373.  
  2374.  
  2375.            /*
  2376.             * Text tables and associated function to display an
  2377.             * unsigned integer value as a string of words.
  2378.             * Note the use of RECURSION to display the number
  2379.             * of thousands and hundreds.
  2380.             */
  2381.    
  2382.            /* Table of single digits and teens */
  2383.            char *digits[] = {
  2384.                "Zero", "One", "Two", "Three", "Four", "Five", "Six",
  2385.                "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve",
  2386.                "Thirteen", "Fourteen", "Fifteen", "Sixteen",
  2387.                "Seventeen", "Eighteen", "Nineteen" };
  2388.    
  2389.            /* Table of tens prefix's */
  2390.            char *tens[] = {
  2391.                "Ten", "Twenty", "Thirty", "Fourty", "Fifty",
  2392.                "Sixty", "Seventy", "Eighty", "Ninety" };
  2393.    
  2394.            /* Function to display number as string */
  2395.            textnum(value)
  2396.                unsigned value;
  2397.            {
  2398.                char join_flag;
  2399.    
  2400.                join_flag = 0;
  2401.    
  2402.                if(value >= 1000) {             /* Display thousands */
  2403.                    textnum(value/1000);
  2404.                    fputs(" Thousand", stdout);
  2405.                    if(!(value %= 1000))
  2406.                        return;
  2407.                    join_flag = 1; }
  2408.    
  2409.                if(value >= 100) {              /* Display hundreds */
  2410.                    if(join_flag)
  2411.                        fputs(", ", stdout);
  2412.                    textnum(value/100);
  2413.                    fputs(" Hundred", stdout);
  2414.                    if(!(value %= 100))
  2415.                        return;
  2416.                    join_flag = 1; }
  2417.    
  2418.                if(join_flag)                   /* Separator if required */
  2419.                    fputs(" and ", stdout);
  2420.    
  2421.                if(value > 19) {                /* Display tens */
  2422.                    fputs(tens[(value/10)-1], stdout);
  2423.                    if(!(value %= 10))
  2424.                        return;
  2425.                    putc(' ', stdout); }
  2426.    
  2427.                fputs(digits[value], stdout);   /* Display digits */
  2428.            }
  2429.  
  2430.  
  2431.  
  2432.                                Intro to MICRO-C
  2433.  
  2434.                               TABLE OF CONTENTS
  2435.  
  2436.  
  2437.                                                                         Page
  2438.  
  2439.     1. INTRODUCTION                                                        1
  2440.  
  2441.  
  2442.     2. BACKGROUND INFORMATION                                              2
  2443.  
  2444.        2.1 Computer Architecture                                           2
  2445.        2.2 Assembly Language                                               5
  2446.        2.3 High Level Languages                                            6
  2447.        2.4 Interpreters VS Compilers                                       8
  2448.        2.5 Object Modules & Linking                                        9
  2449.        2.6 Compiler Libraries                                             10
  2450.        2.7 Portability                                                    10
  2451.  
  2452.     3. INTRODUCTION TO 'C'                                                11
  2453.  
  2454.        3.1 Functions                                                      12
  2455.        3.2 Variables                                                      13
  2456.        3.3 Pointers                                                       16
  2457.        3.4 A complete 'C' program                                         16
  2458.        3.5 'C' memory organization                                        18
  2459.  
  2460.     4. EXPRESSIONS                                                        21
  2461.  
  2462.        4.1 Unary operators                                                22
  2463.        4.2 Binary Operators                                               24
  2464.        4.3 Other Operators                                                29
  2465.  
  2466.     5. CONTROL STATEMENTS                                                 32
  2467.  
  2468.        5.1 The IF statement                                               32
  2469.        5.2 The WHILE Loop                                                 32
  2470.        5.3 The DO/WHILE Loop                                              33
  2471.        5.4 The FOR Loop                                                   34
  2472.        5.5 Compound Statements                                            35
  2473.        5.6 BREAK and CONTINUE                                             36
  2474.        5.7 The SWITCH Statement                                           36
  2475.        5.8 Labels and GOTO                                                37
  2476.  
  2477.     6. RECURSION                                                          38
  2478.  
  2479.  
  2480.     7. COMMAND LINE ARGUMENTS                                             41
  2481.  
  2482.  
  2483.     8. FILE ACCESS                                                        42
  2484.  
  2485.        8.1 File Pointers                                                  42
  2486.  
  2487.    Intro to MICRO-C                                       Table of Contents
  2488.  
  2489.                                                                         Page
  2490.        8.2 File I/O Functions                                             42
  2491.        8.3 Standard I/O                                                   43
  2492.  
  2493.     9. SAMPLE FUNCTIONS                                                   44
  2494.  
  2495.        9.1 Prime Number Generator                                         44
  2496.        9.2 A Simple Sort                                                  45
  2497.        9.3 Text Display of Value                                          46
  2498.